[
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\ncharset = utf-8\nend_of_line = lf\ninsert_final_newline = true\nindent_style = space\nindent_size = 4\n\n[*.json]\nindent_size = 2\n"
  },
  {
    "path": ".eslintignore",
    "content": "packages/testbot\n"
  },
  {
    "path": ".eslintrc.json",
    "content": "{\n    \"parser\": \"@typescript-eslint/parser\",\n    \"plugins\": [\"@typescript-eslint\"],\n    \"extends\": [\"plugin:@typescript-eslint/recommended\"],\n    \"parserOptions\": {\n        \"ecmaVersion\": 9,\n        \"sourceType\": \"module\",\n        \"ecmaFeatures\": {\n            \"impliedStrict\": true\n        }\n    },\n    \"rules\": {\n        \"semi\": [\"error\", \"always\"],\n        \"no-return-await\": 0,\n        \"space-before-function-paren\": [\"error\", {\n            \"named\": \"never\",\n            \"anonymous\": \"never\",\n            \"asyncArrow\": \"always\"\n        }],\n        \"quotes\": [\"error\", \"single\", {\"allowTemplateLiterals\": true}],\n        \"template-curly-spacing\": [\"error\", \"always\"],\n        \"@typescript-eslint/camelcase\": 0,\n        \"@typescript-eslint/indent\": [\"error\", 4],\n        \"@typescript-eslint/interface-name-prefix\": 0,\n        \"@typescript-eslint/no-explicit-any\": 0,\n        \"@typescript-eslint/no-object-literal-type-assertion\": [\"error\", {\n            \"allowAsParameter\": true\n         }],\n         \"@typescript-eslint/no-use-before-define\": [\"error\", { \"functions\": false, \"classes\": true }]\n    }\n}"
  },
  {
    "path": ".github/issue_template.md",
    "content": "\n** DO NOT ERASE THESE INSTRUCTIONS WITHOUT READING THEM FIRST **\n\nPlease read this entire template before posting any issue to get faster response.\n\nOpen an issue on this repository with your topic or question, providing as much detail as possible. The more we know, the better we can help.\n\nBefore posting, search the repository to see if there's already an issue opened to avoid duplicates.\n\n### Are you sure this is an issue with the Botkit core module?\n\nFor all other questions, requests or help, please feel free to join the discussion slack : https://community.botkit.ai\n\n### What are you trying to achieve or the steps to reproduce?\n\nDescribe your issue here, include as much detail as necessary to reproduce the issue or implement a missing functionality.\n\n````\n// Wrap code in markdown source tags\n````\n\n### What was the result you received?\n\n### What did you expect?\n\n### Screenshots and animated GIFs\n\n### Context:\n\n- Botkit version:\n- Messaging Platform:\n- Node version: \n- Os:\n- Any other relevant information:\n"
  },
  {
    "path": ".github/stale.yml",
    "content": "# Number of days of inactivity before an issue becomes stale\ndaysUntilStale: 60\n# Number of days of inactivity before a stale issue is closed\ndaysUntilClose: 7\n# Issues with these labels will never be considered stale\nexemptLabels:\n  - bug\n  - next_release\n  - platform request\n# Label to use when marking an issue as stale\nstaleLabel: stale\n# Comment to post when marking an issue as stale. Set to `false` to disable\nmarkComment: >\n  This issue has been automatically marked as stale because it has not had\n  recent activity. It will be closed if no further activity occurs. Thank you\n  for your contributions.\n# Comment to post when closing a stale issue. Set to `false` to disable\ncloseComment: false\n"
  },
  {
    "path": ".gitignore",
    "content": "node_modules/\nstart.sh\nstart_button.sh\ndb/\nexamples/db_slackbutton_bot/\nexamples/db_slackbutton_incomingwebhook/\nexamples/db_slackbutton_slashcommand/\nexamples/db_team_bot/\n.DS_Store\n*/.DS_Store\n.idea\n.vscode\n.env\ncoverage\n\n# simple_storage files\n/channels/\n/teams/\n/users/\n\n# temp test files\ntests/**/temp/\n"
  },
  {
    "path": ".npmignore",
    "content": "docs/provisioning/IMG\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: node_js\nnode_js:\n- lts/*\nscript:\n- lerna bootstrap --hoist\n- lerna run build\n- lerna run test"
  },
  {
    "path": "ATTRIBUTIONS.md",
    "content": "# bser\n\nCopyright 2015-present Facebook, Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at\n \nhttp://www.apache.org/licenses/LICENSE-2.0\n \nUnless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.\n\n# fb-watchman\n\nCopyright 2014-present Facebook, Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at\n \nhttp://www.apache.org/licenses/LICENSE-2.0\n \nUnless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.\n\n# weak-map\n\nCopyright (c) 2011 Google Inc., Kris Kowal\n\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at\n \nhttp://www.apache.org/licenses/LICENSE-2.0\n \nUnless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.\n\n# browser-process-hrtime\n\nCopyright 2014 kumavis\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n\n1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n\n2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n# remove-trailing-separator\n\nCopyright (c) 2017 Tomas Sardyha <darsain@gmail.com>\n\nPermission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n# xmpp\n\nCopyright (c) 2017, xmpp.js\n\nPermission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n\n# Babel-jest\n\nCopyright (c) 2014-present, Facebook, Inc.\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n# babel code frame\n\nCopyright (c) 2014-2018 Sebastian McKenzie and other contributors\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n# compare-versions\n\nCopyright (c) 2015-2017 Ole Michelsen\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n# babel/highlight\n\nCopyright (c) 2014-2018 Sebastian McKenzie and other contributors\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n# invert-kv\n\nCopyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n# Jest\n\nCopyright (c) 2014-present, Facebook, Inc.\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n# json-stable-stringify\n\nCopyright (c) James Halliday\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n# just-extend\n\nCopyright (c) 2016 angus croll\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n# key-tree-store\n\nCopyright (c) Henrik Joreteg <henrik@andyet.net>\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n# node-xmpp-core\n\nCopyright (c) 2016 node-xmpp\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n# node-xmpp-tls-connect\n\nCopyright (c) 2016 node-xmpp\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n# safe-regex\n\nCopyright (c) James Halliday\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n# sane\n\nsane:\n\nCopyright (c) amasad\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n-----\n\nwatch:\n\nCopyright (c) Mikeal Rogers <mikeal.rogers@gmail.com>\n\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at\n \nhttp://www.apache.org/licenses/LICENSE-2.0\n \nUnless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.\n\n# should-equal\n\nCopyright (c) 2014 Denis Bardadym <bardadymchik@gmail.com>\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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 \nOTHER DEALINGS IN THE SOFTWARE.\n\n# should-format\n\nCopyright (c) 2014 Denis Bardadym <bardadymchik@gmail.com>\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n# should-sinon\n\nCopyright (c) 2015 Denis Bardadym <bardadymchik@gmail.com>\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n# should-type\n\nCopyright (c) 2014 Denis Bardadym <bardadymchik@gmail.com>\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n# slash\n\nCopyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n# to-double-quotes\n\nCopyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n# w3c-hr-time\n\nCopyright (c) 2017 Tiancheng \"Timothy\" Gu and other contributors\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n# wordwrap\n\nCopyright (c) James Halliday\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n# json-schema\n\nThe \"New\" BSD License:\n**********************\n\nCopyright (c) 2005-2018, The JS Foundation\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n\n  * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n  * Neither the name of the JS Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n# browser-request\n\nCopyright (c) 2014 Jason Smith Work <jhs@iriscouch.com>, Jason Smith <jason.h.smith@gmail.com>, maxogden <max@maxogden.com>\n\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.\n\n# scmp\n\nCopyright (c) 2014, Sean Lavine\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n* Neither the name of the scmp project nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n# spdx-exceptions\n\nspdx-exceptions.json (c) 2010-2015 Linux Foundation and its Contributors.\n\nspdx-exceptions.json is licensed under a Creative Commons Attribution 3.0 Unported License (CC BY 3.0) License.\n\nYou should have received a copy of the license along with this work.  If not, see https://creativecommons.org/licenses/by/3.0/legalcode.\n\n\n# xmpp.js\n\nCopyright (c) 2017, xmpp.js\n\nPermission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n# ampersand-version\n\nCopyright (c) 2014 &yet, LLC and AmpersandJS contributors\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n# array-next\n\nCopyright (c) Henrik Joreteg\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n\n# babel\n\nCopyright (c) 2014-2018 Sebastian McKenzie and other contributors\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n\n# botbuilder\n\nCopyright (c) 2016 Microsoft\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n\n# botkit-studio-sdk\n\nCopyright (c) howdyai\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n\n# ciscospark\n\nCopyright (c) 2016-2018 Cisco and/or its affiliates. All Rights Reserved.\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n# concat-map\n\nCopyright (c) James Halliday\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n# deep-equal\n\nCopyright (c) James Halliday\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n# deprecate\n\nCopyright (c) Brian M. Carlson\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n# envify\n\nCopyright (c) Hugh Kennedy <hughskennedy@gmail.com> (http://hughskennedy.com/)\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n# es6-promisify\n\nCopyright (c) 2014 Mike Hall / Digital Design Labs\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n# exit-hook\n\n\"Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\"\n\n\n# fast-json-stable-stringify\n\nCopyright (c) James Halliday\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n# i\n\nCopyright (c) Pavan Kumar Sunkara\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n\n# inquirer\n\nCopyright (c) 2012 Simon Boudrias\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n# is-typedarray\n\nCopyright (c) Hugh Kennedy <hughskennedy@gmail.com> (http://hughsk.io/)\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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 \nOR 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.\n\n\n# jsdoctypeparser\n\n\"Copyright (c) 2018 Kuniwak\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\"\n\n\n# minimist\n\nCopyright (c) James Halliday\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n\n# node-xmpp-client\n\nCopyright (c) 2016 node-xmpp\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n# openurl\n\nCopyright (c) Axel Rauschmayer <axe@rauschma.de>\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n# pop-iterate\n\nCopyright (c) Kris Kowal <kris@cixar.com>\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n# qbox\n\nCopyright (c) Arunoda Susiripala <arunoda.susiripala@gmail.com>\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n# readline2 \nCopyright (c) 2014 Simon Boudrias\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n# regenerator-runtime\n\nCopyright (c) 2014-present, Facebook, Inc.\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n\n# resolve\n\nCopyright (c) James Halliday\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n# rootpath\n\nCopyright (c) Fabrizio Moscon <mosconfabrizio@gmail.com>\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Instructions for Contributing Code\n\nThis project welcomes contributions and suggestions.  Most contributions require you to agree to a\nContributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us\nthe rights to use your contribution. For details, visit https://cla.microsoft.com.\n\nWhen you submit a pull request, a CLA-bot will automatically determine whether you need to provide\na CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions\nprovided by the bot. You will only need to do this once across all repos using our CLA.\n\nWhen you submit a pull request, a CLA-bot will automatically determine whether you need to provide\na CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions\nprovided by the bot. You will only need to do this once across all repos using our CLA.\n\n## Code of Conduct\n\nThis project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.\n\n## Submitting Issues\n\n* You can create an issue [here](https://github.com/howdyai/botkit/issues/new),\nbut before doing that please read the notes below and include as many details as\npossible with your report. If you can, please include:\n  * The version of Botkit you are using\n  * The operating system you are using\n  * If applicable, what you were doing when the issue arose and what you\n  expected to happen\n* Other things that will help resolve your issue:\n  * Screenshots and animated GIFs\n  * Error output that appears in your terminal, dev tools or as an alert\n  * Perform a [cursory search](https://github.com/howdyai/botkit/issues?utf8=✓&q=is%3Aissue+)\n  to see if a similar issue has already been submitted\n\n## Submitting Pull Requests\n\n* Pull requests should contain a concise topic and detailed accompanying text that clearly identifies both the purpose and justification for acceptance of any changes.\n* Create, or link to an existing issue identifying the need driving your PR request. The issue can contain more details of the need for the PR as well as host debate as to which course of action the PR will take that will most serve the common good.\n* Include screenshots and animated GIFs in your pull request whenever possible.\n* Run `npm test` before submitting and fix any issues.\n* Add tests to cover any new functionality. Add and/or update tests for any updates to the code.\n* Write documentation in [Markdown](https://daringfireball.net/projects/markdown).\n* Please follow, [JSDoc](http://usejsdoc.org/) for proper documentation.\n* Use short, present tense commit messages. See [Commit Message Styleguide](#git-commit-messages).\n\n## Styleguides\n\n### General Code\n\n* End files with a newline.\n* Place requires in the following order:\n  * Built in Node Modules (such as `path`)\n  * Local Modules (using relative paths)\n* Avoid platform-dependent code:\n  * Use `path.join()` to concatenate filenames.\n* Using a plain `return` when returning explicitly at the end of a function.\n  * Not `return null`, `return undefined`, `null`, or `undefined`\n\n### Git Commit Messages\n\n* Use the present tense (\"Add feature\" not \"Added feature\")\n* Use the imperative mood (\"Move cursor to...\" not \"Moves cursor to...\")\n* Limit the first line to 72 characters or less\n* Reference issues and pull requests liberally\n"
  },
  {
    "path": "LICENSE.md",
    "content": "Copyright XOXCO, Inc, http://xoxco.com, http://howdy.ai\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "build/botkit-ci.yml",
    "content": "# Node.js\n# Build a general Node.js project with npm.\n# Add steps that analyze code, save build artifacts, deploy, and more:\n# https://docs.microsoft.com/azure/devops/pipelines/languages/javascript\n\n# \"name\" here defines the build number format. Build number is accessed via $(Build.BuildNumber)\nname: $(Build.BuildId)\n\npool:\n  vmImage: windows-latest\n\ntrigger: none # ci trigger is set in ADO\npr: none # pr trigger is set in ADO\n\nvariables:\n  runCodesignValidationInjection: false\n\nsteps:\n- task: NodeTool@0\n  inputs:\n    versionSpec: '14.x'\n    checkLatest: true\n  displayName: 'Install Node.js 14.x'\n\n- task: Bash@3\n  inputs:\n    targetType: 'inline'\n    script: |\n      rm -r packages/testbot\n      rm -r packages/docs\n      \n      echo \"rebase main package-lock\"\n      cat package-lock.json | node build/scripts/rebasePackageLock.js https://fuselabs.pkgs.visualstudio.com/_packaging/FuseNPM/npm/registry/ > new-package-lock.json\n      echo \"moving file...\"\n      mv new-package-lock.json package-lock.json\n      \n      echo \"rebase facebook adapter\"\n      cat packages/botbuilder-adapter-facebook/package-lock.json | node build/scripts/rebasePackageLock.js https://fuselabs.pkgs.visualstudio.com/_packaging/FuseNPM/npm/registry/ > packages/botbuilder-adapter-facebook/new-package-lock.json\n      echo \"moving file...\"\n      mv packages/botbuilder-adapter-facebook/new-package-lock.json packages/botbuilder-adapter-facebook/package-lock.json\n      \n      echo \"rebase hangouts adapter\"\n      cat packages/botbuilder-adapter-hangouts/package-lock.json | node build/scripts/rebasePackageLock.js https://fuselabs.pkgs.visualstudio.com/_packaging/FuseNPM/npm/registry/ > packages/botbuilder-adapter-hangouts/new-package-lock.json\n      mv packages/botbuilder-adapter-hangouts/new-package-lock.json packages/botbuilder-adapter-hangouts/package-lock.json\n      \n      echo \"rebase slack adapter...\"\n      cat packages/botbuilder-adapter-slack/package-lock.json | node build/scripts/rebasePackageLock.js https://fuselabs.pkgs.visualstudio.com/_packaging/FuseNPM/npm/registry/ > packages/botbuilder-adapter-slack/new-package-lock.json\n      mv packages/botbuilder-adapter-slack/new-package-lock.json packages/botbuilder-adapter-slack/package-lock.json\n      \n      echo \"rebase twilio adapter...\"\n      cat packages/botbuilder-adapter-twilio-sms/package-lock.json | node build/scripts/rebasePackageLock.js https://fuselabs.pkgs.visualstudio.com/_packaging/FuseNPM/npm/registry/ > packages/botbuilder-adapter-twilio-sms/new-package-lock.json\n      mv packages/botbuilder-adapter-twilio-sms/new-package-lock.json packages/botbuilder-adapter-twilio-sms/package-lock.json\n      \n      echo \"rebase web adapter...\"\n      cat packages/botbuilder-adapter-web/package-lock.json | node build/scripts/rebasePackageLock.js https://fuselabs.pkgs.visualstudio.com/_packaging/FuseNPM/npm/registry/ > packages/botbuilder-adapter-web/new-package-lock.json\n      mv packages/botbuilder-adapter-web/new-package-lock.json packages/botbuilder-adapter-web/package-lock.json\n      \n      echo \"rebase webex adapter...\"\n      cat packages/botbuilder-adapter-webex/package-lock.json | node build/scripts/rebasePackageLock.js https://fuselabs.pkgs.visualstudio.com/_packaging/FuseNPM/npm/registry/ > packages/botbuilder-adapter-webex/new-package-lock.json\n      mv packages/botbuilder-adapter-webex/new-package-lock.json packages/botbuilder-adapter-webex/package-lock.json\n      \n      echo \"rebase cms plugin...\"\n      cat packages/botkit-plugin-cms/package-lock.json | node build/scripts/rebasePackageLock.js https://fuselabs.pkgs.visualstudio.com/_packaging/FuseNPM/npm/registry/ > packages/botkit-plugin-cms/new-package-lock.json\n      mv packages/botkit-plugin-cms/new-package-lock.json packages/botkit-plugin-cms/package-lock.json\n      \n      echo \"rebase botkit...\"\n      cat packages/botkit/package-lock.json | node build/scripts/rebasePackageLock.js https://fuselabs.pkgs.visualstudio.com/_packaging/FuseNPM/npm/registry/ > packages/botkit/new-package-lock.json\n      mv packages/botkit/new-package-lock.json packages/botkit/package-lock.json\n      \n      echo \"rebase generator...\"\n      cat packages/generator-botkit/package-lock.json | node build/scripts/rebasePackageLock.js https://fuselabs.pkgs.visualstudio.com/_packaging/FuseNPM/npm/registry/ > packages/generator-botkit/new-package-lock.json\n      mv packages/generator-botkit/new-package-lock.json packages/generator-botkit/package-lock.json\n  displayName: 'Set up for FuseNPM feed'\n\n- task: Bash@3\n  inputs:\n    targetType: 'inline'\n    script: |\n      npm install --ignore-scripts\n      lerna bootstrap --hoist\n      lerna run build\n      lerna run pack\n  displayName: 'Build packages'\n\n- task: ComponentGovernanceComponentDetection@0\n  displayName: 'Component Detection'\n  inputs:\n    scanType: 'Register'\n    verbosity: 'Verbose'\n    alertWarningLevel: 'High'\n    failOnAlert: false\n\n- task: CredScan@3\n\n- powershell: |\n    Get-ChildItem .. -ErrorAction Continue -Recurse -Force | Where {$_.FullName -notlike \"*node_modules*\"}\n  displayName: 'Dir workspace except node_modules'\n  continueOnError: true\n  condition: succeededOrFailed()\n"
  },
  {
    "path": "build/botkit-daily.yml",
    "content": "# Node.js\n# Build a general Node.js project with npm.\n# Add steps that analyze code, save build artifacts, deploy, and more:\n# https://docs.microsoft.com/azure/devops/pipelines/languages/javascript\n\n# \"name\" here defines the build number format. Build number is accessed via $(Build.BuildNumber)\nname: $(Build.BuildId)\n\npool:\n  vmImage: windows-latest\n\ntrigger: none # ci trigger is set in ADO\npr: none # pr trigger is set in ADO\n\nvariables:\n  Packaging.EnableSBOMSigning: true\n  runCodesignValidationInjection: false\n#  PackageVersion: 4.16.0-dev.{DateStamp}.$(Build.BuildId) Define this in Azure to be settable at queue time.\n\nsteps:\n- task: NodeTool@0\n  inputs:\n    versionSpec: '14.x'\n    checkLatest: true\n  displayName: 'Install Node.js 14.x'\n\n- powershell: |\n    # Replace {DateStamp} with the actual value in var PackageVersionFormat\n    $dateStamp = (Get-Date -format \"yyyyMMdd\");\n    \n    \"Raw PackageVersion = $(PackageVersion)\";\n    $v = \"$(PackageVersion)\".Replace(\"{DateStamp}\",$dateStamp);\n    Write-Host \"##vso[task.setvariable variable=PackageVersion;]$v\";\n    \"Resolved PackageVersion = $v\";\n  displayName: 'Resolve variable PackageVersion'\n\n- powershell: |\n    Get-ChildItem -Recurse -Path 'packages\\botkit\\package.json' | % {\n        $_.FullName; \n        $content = Get-Content -Raw $_.FullName | ConvertFrom-Json;\n        $content.version = \"$(PackageVersion)\";\n        $content | ConvertTo-Json | Set-Content $_.FullName;\n        '-------------'; get-content $_.FullName; '==================='\n    }\n  displayName: 'Set botkit package version'\n\n- task: colinsalmcorner.colinsalmcorner-buildtasks.tag-build-task.tagBuildOrRelease@0\n  displayName: tag build with version number\n  inputs:\n    tags: |\n     version=$(PackageVersion)\n  continueOnError: true\n\n- task: Bash@3\n  inputs:\n    targetType: 'inline'\n    script: |\n      rm -r packages/testbot\n      rm -r packages/docs\n      \n      echo \"rebase main package-lock\"\n      cat package-lock.json | node build/scripts/rebasePackageLock.js https://fuselabs.pkgs.visualstudio.com/_packaging/FuseNPM/npm/registry/ > new-package-lock.json\n      echo \"moving file...\"\n      mv new-package-lock.json package-lock.json\n      \n      echo \"rebase facebook adapter\"\n      cat packages/botbuilder-adapter-facebook/package-lock.json | node build/scripts/rebasePackageLock.js https://fuselabs.pkgs.visualstudio.com/_packaging/FuseNPM/npm/registry/ > packages/botbuilder-adapter-facebook/new-package-lock.json\n      echo \"moving file...\"\n      mv packages/botbuilder-adapter-facebook/new-package-lock.json packages/botbuilder-adapter-facebook/package-lock.json\n      \n      echo \"rebase hangouts adapter\"\n      cat packages/botbuilder-adapter-hangouts/package-lock.json | node build/scripts/rebasePackageLock.js https://fuselabs.pkgs.visualstudio.com/_packaging/FuseNPM/npm/registry/ > packages/botbuilder-adapter-hangouts/new-package-lock.json\n      mv packages/botbuilder-adapter-hangouts/new-package-lock.json packages/botbuilder-adapter-hangouts/package-lock.json\n      \n      echo \"rebase slack adapter...\"\n      cat packages/botbuilder-adapter-slack/package-lock.json | node build/scripts/rebasePackageLock.js https://fuselabs.pkgs.visualstudio.com/_packaging/FuseNPM/npm/registry/ > packages/botbuilder-adapter-slack/new-package-lock.json\n      mv packages/botbuilder-adapter-slack/new-package-lock.json packages/botbuilder-adapter-slack/package-lock.json\n      \n      echo \"rebase twilio adapter...\"\n      cat packages/botbuilder-adapter-twilio-sms/package-lock.json | node build/scripts/rebasePackageLock.js https://fuselabs.pkgs.visualstudio.com/_packaging/FuseNPM/npm/registry/ > packages/botbuilder-adapter-twilio-sms/new-package-lock.json\n      mv packages/botbuilder-adapter-twilio-sms/new-package-lock.json packages/botbuilder-adapter-twilio-sms/package-lock.json\n      \n      echo \"rebase web adapter...\"\n      cat packages/botbuilder-adapter-web/package-lock.json | node build/scripts/rebasePackageLock.js https://fuselabs.pkgs.visualstudio.com/_packaging/FuseNPM/npm/registry/ > packages/botbuilder-adapter-web/new-package-lock.json\n      mv packages/botbuilder-adapter-web/new-package-lock.json packages/botbuilder-adapter-web/package-lock.json\n      \n      echo \"rebase webex adapter...\"\n      cat packages/botbuilder-adapter-webex/package-lock.json | node build/scripts/rebasePackageLock.js https://fuselabs.pkgs.visualstudio.com/_packaging/FuseNPM/npm/registry/ > packages/botbuilder-adapter-webex/new-package-lock.json\n      mv packages/botbuilder-adapter-webex/new-package-lock.json packages/botbuilder-adapter-webex/package-lock.json\n      \n      echo \"rebase cms plugin...\"\n      cat packages/botkit-plugin-cms/package-lock.json | node build/scripts/rebasePackageLock.js https://fuselabs.pkgs.visualstudio.com/_packaging/FuseNPM/npm/registry/ > packages/botkit-plugin-cms/new-package-lock.json\n      mv packages/botkit-plugin-cms/new-package-lock.json packages/botkit-plugin-cms/package-lock.json\n      \n      echo \"rebase botkit...\"\n      cat packages/botkit/package-lock.json | node build/scripts/rebasePackageLock.js https://fuselabs.pkgs.visualstudio.com/_packaging/FuseNPM/npm/registry/ > packages/botkit/new-package-lock.json\n      mv packages/botkit/new-package-lock.json packages/botkit/package-lock.json\n      \n      echo \"rebase generator...\"\n      cat packages/generator-botkit/package-lock.json | node build/scripts/rebasePackageLock.js https://fuselabs.pkgs.visualstudio.com/_packaging/FuseNPM/npm/registry/ > packages/generator-botkit/new-package-lock.json\n      mv packages/generator-botkit/new-package-lock.json packages/generator-botkit/package-lock.json\n  displayName: 'Set up for FuseNPM feed'\n\n- task: Bash@3\n  inputs:\n    targetType: 'inline'\n    script: |\n      npm install --ignore-scripts\n      lerna bootstrap --hoist\n      lerna run build\n      lerna run pack\n  displayName: 'Build packages'\n\n- task: CopyFiles@2\n  displayName: copy .tgz files to staging area\n  inputs:\n    SourceFolder: packages\n    Contents: '*/*.tgz'\n    TargetFolder: '$(Build.ArtifactStagingDirectory)/drop'\n    flattenFolders: true\n\n- task: ComponentGovernanceComponentDetection@0\n  displayName: 'Component Detection'\n  inputs:\n    scanType: 'Register'\n    verbosity: 'Verbose'\n    alertWarningLevel: 'High'\n    failOnAlert: false\n\n- task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0\n  displayName: 'Generate Software Bill of Materials (SBOM)'\n  inputs:\n    BuildDropPath: '$(Build.ArtifactStagingDirectory)/drop'\n    PackageName: 'Botkit'\n    PackageVersion: $(PackageVersion)\n\n- task: PublishBuildArtifacts@1\n  displayName: 'Push .tgz files to Artifacts drop'\n  inputs:\n    PathtoPublish: '$(Build.ArtifactStagingDirectory)\\drop'\n    ArtifactName: drop\n\n- powershell: |\n    Get-ChildItem .. -ErrorAction Continue -Recurse -Force | Where {$_.FullName -notlike \"*node_modules*\"}\n  displayName: 'Dir workspace except node_modules'\n  continueOnError: true\n  condition: succeededOrFailed()\n"
  },
  {
    "path": "build/scripts/rebasePackageLock.js",
    "content": "#!/bin/node\n\n'use strict';\n\n// Usage:\n//   cat package-lock.json | node rebasePackageLock.mjs https://your-project.pkgs.visualstudio.com/_packaging/your-feed/npm/registry/ > new-package-lock.json\n\nasync function readAllStdin() {\n  return new Promise((resolve, reject) => {\n    const bufferList = [];\n    let numBytes = 0;\n\n    process.stdin.on('close', () => {\n      resolve(Buffer.concat(bufferList, numBytes));\n    });\n\n    process.stdin.on('data', buffer => {\n      bufferList.push(buffer);\n      numBytes += buffer.length;\n    });\n\n    process.stdin.on('error', reject);\n  });\n}\n\nfunction rebaseV1Inline(name, dependency, baseURL) {\n  const { resolved: actual, version } = dependency;\n  const singleName = name.split('/').reverse()[0];\n\n  const { href: expected } = new URL(`${name}/-/${singleName}-${version}.tgz`, 'https://registry.npmjs.org/');\n  const { href: rebased } = new URL(`${name}/-/${singleName}-${version}.tgz`, baseURL);\n\n  if (expected !== actual) {\n    throw new Error(`v1: Expecting \"resolved\" field to be \"${expected}\", actual is \"${actual}\".`);\n  }\n\n  dependency.resolved = rebased;\n\n  rebaseV1InlineAll(dependency, baseURL);\n}\n\nfunction rebaseV1InlineAll({ dependencies }, baseURL) {\n  for (const [name, dependency] of Object.entries(dependencies || {})) {\n    rebaseV1Inline(name, dependency, baseURL);\n  }\n}\n\nfunction rebaseV2Inline(path, dependency, baseURL) {\n  const { resolved: actual, version } = dependency;\n  const name = path.split('node_modules/').reverse()[0];\n\n  const singleName = name.split('/').reverse()[0];\n\n  const { href: expected } = new URL(`${name}/-/${singleName}-${version}.tgz`, 'https://registry.npmjs.org/');\n  const { href: rebased } = new URL(`${name}/-/${singleName}-${version}.tgz`, baseURL);\n\n  if (expected !== actual) {\n    throw new Error(`v2: Expecting \"resolved\" field to be \"${expected}\", actual is \"${actual}\".`);\n  }\n\n  dependency.resolved = rebased;\n}\n\nfunction rebaseV2InlineAll(packages, baseURL) {\n  for (const [path, dependency] of Object.entries(packages || {})) {\n    // \"path\" is falsy if it is iterating the current package.\n    path && rebaseV2Inline(path, dependency, baseURL);\n  }\n}\n\nasync function main() {\n  const baseURL = process.argv[2];\n\n  if (!baseURL) {\n    throw new Error('New registry base URL must be passed as first argument.');\n  }\n\n  const packageLockJSON = JSON.parse(await readAllStdin());\n\n  // v1\n  rebaseV1InlineAll(packageLockJSON, baseURL);\n\n  // v2\n  rebaseV2InlineAll(packageLockJSON.packages, baseURL);\n\n  const json = JSON.stringify(packageLockJSON, null, 2);\n\n  if (~json.indexOf('://registry.npmjs.org')) {\n    throw new Error('After rebase, \"://registry.npmjs.org\" should not be detected in the output.');\n  }\n\n  console.log(json);\n}\n\nmain();\n"
  },
  {
    "path": "changelog.md",
    "content": "# Change Log\n\n[View the official Botkit roadmap](https://github.com/howdyai/botkit/projects/9) for upcoming changes and features.\n\n[Want to contribute? Read our guide!](https://github.com/howdyai/botkit/blob/master/CONTRIBUTING.md)\n\n# 4.15.0\n\n* Update dependencies to Bot Framework 4.15\n* Update various dev dependencies and external libraries\n* CHANGE: Correct `from` field to be user rather than bot with Slack button clicks. Thanks to [@mdrichardson](https://github.com/mdrichardson) for the [pull request](https://github.com/howdyai/botkit/pull/2089).\n\n# 4.10.0\n\n* Update dependencies to [Bot Framework 4.10.1](https://github.com/microsoft/botbuilder-js/releases/tag/4.10)\n* Update some dev dependencies like lerna, eslint, etc.\n\n* NEW: Additional support for Microsoft Teams! [Read all about it](packages/docs/core.md#ms-teams-extensions) or [see these new methods in action](packages/testbot/features/teams_features.js)\n  * Bot workers spawned from the default adapter now feature `bot.teams` which is an instance to the [TeamsInfo helper class](https://docs.microsoft.com/en-us/javascript/api/botbuilder/teamsinfo?view=botbuilder-ts-latest). \n  * Botkit now includes an optional middleware [TeamsInvokeMiddleware](packages/docs/reference/core.md#TeamsInvokeMiddleware) for handling \"invoke\" responses from Teams including task modules.\n  * Botkit now includes [bot.replyWithTaskInfo()](packages/docs/reference/core.md#replyWithTaskInfo) which can be used to respond to task module events. [Read more about Task Modules](https://docs.microsoft.com/en-us/microsoftteams/platform/task-modules-and-cards/what-are-task-modules)\n\n* FIX: Adjust mechanism for handling templates in channelData to avoid data loss. Thanks [@ashitikov](https://github.com/ashitikov) for the [pull request](https://github.com/howdyai/botkit/pull/1979)\n* FIX: Botkit will now spawn the appropriate botworker if a custom adapter is passed in. Thanks to [@etiennellipse](https://github.com/etiennellipse) for [reporting this issue](https://github.com/howdyai/botkit/issues/1984)!\n\n# 4.9.0\n\n* Update dependencies to [Bot Framework 4.9](https://github.com/microsoft/botbuilder-js/releases/tag/4.9.0)\n* Update some dev dependencies like lerna, mocha and nyc\n\n* FIX: Allow size limits to be adjusted on the Express json and urlencoded parsers. Fixes [#1941](https://github.com/howdyai/botkit/issues/1941)\n* FIX: Allow bots to be spawned with null config. Thanks to [@NxP4Code](https://github.com/NxP4Code) for [this pull request](https://github.com/howdyai/botkit/pull/1955)\n* FIX: Fix dynamic text field type definition. Thanks to [@etienneellipse](https://github.com/etiennellipse) for [this pull request](https://github.com/howdyai/botkit/pull/1960)\n\n# 4.8.1\n\n* FIX: Fixing a bug introduced in 4.8 pertaining to spawning proactive bots for Slack. [#1937](https://github.com/howdyai/botkit/issues/1937)\n\n\n# 4.8\n\nIn addition to fixing a bunch of bugs and adding some new features, this version brings Botkit up to date with Bot Framework's latest release - [Change log here](https://github.com/microsoft/botbuilder-js/releases). \n\nThere are lots of interesting things happening in the Bot Framework world including a new [GUI for dialog management called Bot Framework Composer](https://github.com/microsoft/botframework-composer), a new templating system called [Language Generation](https://github.com/microsoft/BotBuilder-Samples/tree/master/experimental/language-generation), and more. Check out the [main hub repo for more information.](https://github.com/microsoft/botframework-sdk#readme)\n\n### NEW \n\n* NEW: At long last, the convo.ask callbacks can receive the full incoming message payload in addition to the text content.\nThis allows developers to use payload values inside quick replies, button clicks and other rich operations. Many thanks to [@naikus](https://github.com/naikus) for the effort and patience it took to get this in! [PR #1801](https://github.com/howdyai/botkit/pull/1801)\n* NEW: Multi-adapter support improved. Botkit will now spawn the appropriate type of Botworker when used in a multi-adapter scenario. [See this example for a demonstration of using multiple adapters in a single bot app](./packages/testbot/multiadapter.js). [Issue #1920](https://github.com/howdyai/botkit/issues/1920)\n* NEW: Add support for Slack's v2 oauth. [More details here](./packages/botbuilder-adapter-slack/CHANGELOG.md#109). Thanks to [@sfny](https://github.com/sfny) for [PR #1928](https://github.com/howdyai/botkit/pull/1928)\n* NEW: Values in `channelData` will now be processed as Mustache templates inside BotkitConversations. [Thanks @me-cedric](https://github.com/me-cedric) for [pr #1925](https://github.com/howdyai/botkit/pull/1925)\n* NEW: New Dialog related features for determining if a bot is already in a conversation, including [bot.hasActiveDialog()](packages/docs/reference/core.md#hasActiveDialog),\n[bot.getActiveDialog()](packages/docs/reference/core.md#getActiveDialog), and\n[bot.isDialogActive()](packages/docs/reference/core.md#isDialogActive) \n\n### FIXED\n\n* FIX: Facebook Adapter will not attempt to set up web routes if webserver is not configured. [#1916](https://github.com/howdyai/botkit/issues/1916)\n* FIX: Exclude `activity.conversation.properties` field when generating state storage key. [#1849](https://github.com/howdyai/botkit/issues/1849)\n* FIX: Allow startConversationWithUser to work with Bot Framework Emulator. [#1834](https://github.com/howdyai/botkit/issues/1834)\n* FIX: Using `beginDialog` inside an `ask()` caused weird behaviors.  Fixes for [#1878](https://github.com/howdyai/botkit/issues/1878) and [#1932](https://github.com/howdyai/botkit/issues/1932)\n* FIX: Webex - remove empty `files` key [#1906](https://github.com/howdyai/botkit/pull/1906)\n* FIX: Slack - authed_users added to message [#1911](https://github.com/howdyai/botkit/issues/1911)\n* Update: all dependencies to latest, including bot framework 4.7->4.8 and mustache 3.0 -> 4.0\n\n# 4.6.1\n\nVersion 4.6.1 includes some security and bugfix updates along with bumping many dependencies to the latest versions.\nWe recommend updating both Botkit core and your platform adapter to the latest version.\n\n* Update Bot Framework dependencies to 4.7.1.  Resolved [#1882](https://github.com/howdyai/botkit/issues/1882) and [#1894](https://github.com/howdyai/botkit/issues/1894).\n* Remove `hbs` depencency from Botkit. Not used! Thanks @naktibaldi [#1855](https://github.com/howdyai/botkit/pull/1855)\n* Botkit feature modules can now be written in ES6 syntax. Thanks @cooperka!! [#1854](https://github.com/howdyai/botkit/pull/1854)\n* Allow `attachmentLayout` field in Botkit Conversations -- thanks @innorag [#1865](https://github.com/howdyai/botkit/pull/1865)\n* Update dependencies and some minor eslint syntax fixes across all the adapters and sub-packages.\n* Fixes in [botbuilder-adapter-slack](packages/botbuilder-adapter-slack/CHANGELOG.md#108)\n* Fixes in [botbuilder-adapter-web](packages/botbuilder-adapter-web/CHANGELOG.md#106)\n\n\n# 4.6\n\nVersion 4.6 includes security and bugfix updates to many dependencies, as well as fixes to some issues in Botkit core.\nWe recommend updating both Botkit core and your platform adapter to the latest version.\n\n**New Features**\n* Add a new `BotkitTestClient` class that makes it possible to write unit tests for dialogs. See [EXAMPLE UNIT TESTS HERE](https://github.com/howdyai/botkit/blob/master/packages/botkit/tests/Dialog.tests.js) -- [HUGE HUGE thanks to @qwertyuu for leading the effort on this!](https://github.com/howdyai/botkit/pull/1815)\n* Support .ts (or parameterized) file extensions for loadModules [Thanks to @mutmatt for the PR](https://github.com/howdyai/botkit/pull/1777)\n* The `text` field in a BotkitConversations can now be a function, which can be used to generated internationalized strings. [Thanks to @cooperka for the PR](https://github.com/howdyai/botkit/pull/1747)\n* Add `convo.stop()` to allow conversation to be ended inside a handler.\n* Update yeoman generator to make all environment variables UPPERCASE\n\n**Fixes**\n* Fix usePlugin parameter type declaration [thanks to @etiennellipse](https://github.com/howdyai/botkit/pull/1836)\n* Fix ask/addQuestion type signatures [thanks to @etiennellipse](https://github.com/howdyai/botkit/pull/1818)\n* Fix to how messages are constructed inside BotkitConversations. [thanks to @adantoscano](https://github.com/howdyai/botkit/pull/1746)\n* Fail with better error when thread not found [Thanks to @cooperka](https://github.com/howdyai/botkit/pull/1758)\n* correct mustache rendering from causing mutation of initial dialog script [Thanks to @InnoraG](https://github.com/howdyai/botkit/pull/1761)\n* Fix: allow BotkitPlugins to have additional fields [Thanks to @roeintense](https://github.com/howdyai/botkit/issues/1804)\n* Fix: resolve issues where calling cancelAllDialogs() would crash [thanks to @etiennellipse](https://github.com/howdyai/botkit/issues/1808)\n* Fix: resolve issue where calling cancelAllDialogs() could cause repeat [thanks to @chahat-arora](https://github.com/howdyai/botkit/issues/1830)\n* Fix: resolve issue where calling convo.repeat() would cause errors [thanks to akshaykonjier](https://github.com/howdyai/botkit/issues/1673) and [also to @etiennellipse](https://github.com/howdyai/botkit/issues/1811)\n\nThis update includes the following packages:\n\n* Botkit v4.6.0\n* generator-botkit v4.6.0\n* [botbuilder-adapter-web v1.0.5](packages/botbuilder-adapter-web/CHANGELOG.md#105)\n* [botbuilder-adapter-slack v1.0.6](packages/botbuilder-adapter-slack/CHANGELOG.md#106)\n* [botbuilder-adapter-webex v1.0.4](packages/botbuilder-adapter-webex/CHANGELOG.md#104)\n* [botbuilder-adapter-facebook v1.0.6](packages/botbuilder-adapter-facebook/CHANGELOG.md#106)\n* [botbuilder-adapter-hangouts v1.0.4](packages/botbuilder-adapter-hangouts/CHANGELOG.md#103)\n* [botbuilder-adapter-twilio-sms v1.0.4](packages/botbuilder-adapter-twilio-sms/CHANGELOG.md#104)\n* [botkit-plugin-cms v1.0.3](packages/botkit-plugin-cms/CHANGELOG.md#103)\n\n# 0.7.5\n\nA maintenance release to the legacy branch was released as 0.7.5.\n\n* Update out of date dependencies to address security issues\n* Add support for Slack's new modals\n\n# 4.5\n\nWe're skipping a few version numbers here to keep in sync with the rest of [Microsoft Bot Framework](https://github.com/microsoft/botframework).\nWelcome to Botkit 4.5!  This release contains a host of improvements and bug fixes affecting Botkit's conversation system, as well the behavior\nof some of the platform adapters.  We recommend that all developers currently using Botkit v4 upgrade to 4.5. \n\nSpecific Changes: \n\n* NEW: It is now possible to create dynamic quick replies, and attachments within a BotkitConversation. [See full docs](https://botkit.ai/docs/v4/conversations.html#dynamic-quick-replies-and-attachments).\n* NEW: Previously, there was no way to bind middleware to the internally created Express webserver. It is now possible to do so using the `webserver_middlewares` parameter.  [Full docs](https://botkit.ai/docs/v4/reference/slack.html#interface-slackadapteroptions)\n* NEW: Quick replies and suggestedActions are now procssed as mustache templates. Thanks to [@InnoraG](https://github.com/innorag) for [the pull request](https://github.com/howdyai/botkit/pull/1731).\n* NEW: Slack block actions and other button clicks now are message type events and get included in dialogs. Thanks to [@apemberton](https://github.com/apemberton) for the [pull request](https://github.com/howdyai/botkit/pull/1712).\n* NEW: The key name passed in to convo.ask and convo.addQuestion can now be set to null in order to discard the answer. Thanks to [@adantoscano](https://github.com/adantoscano) for [the pull request](https://github.com/howdyai/botkit/pull/1716)\n\n\n* FIX: Botkit will no longer improperly prune platform specific fields like quick replies and attachments specified inside BotkitConversations. [Fix for #1664](https://github.com/howdyai/botkit/issues/1664), [#1679](https://github.com/howdyai/botkit/issues/1679), and [#1699](https://github.com/howdyai/botkit/issues/1699).\n* FIX: The text field in BotkitConversations was expected to always be an array, causing some confusion. It is now possible to pass in a string OR an array. Passing an array will cause Botkit to choose a random entry in the array for the message text.\n* FIX: Several updates have been made to the middleware pipeline so that it better matches expected behavior.  The receive and send middlewares will now fire for every incoming message - previously, there were cases where these would not fire. Thanks to [@adantoscano](https://github.com/adantoscano) for [this pull request](https://github.com/howdyai/botkit/pull/1717) and also [this one](https://github.com/howdyai/botkit/pull/1720). \n* FIX: The method for passing in a URI for communicating with Botkit CMS has been made more reliable, thanks to [@adantoscano](https://github.com/adantoscano). [See #1675](https://github.com/howdyai/botkit/pull/1675) and [#1677](https://github.com/howdyai/botkit/pull/1677).\n* FIX: Webex adapter has been updated to better support file uploads. Thanks to [@Teamop](https://github.com/Teamop) for [the pull request](https://github.com/howdyai/botkit/pull/1667)\n* FIX: Improve mapping of Bot Framework \"Activity\" fields. Thanks to [@Naktibalda](https://github.com/Naktibalda) for [the pull request](https://github.com/howdyai/botkit/pull/1707).\n* FIX: Expand typedefs for Slack dialogs. Thanks to [@roger-king](https://github.com/roger-king) for [the pull request](https://github.com/howdyai/botkit/pull/1653)\n\n\n* UPDATE: Update to v4.5.2 of all Bot Framework packages\n* UPDATE: `ws` websocket module updated to v7.1.1\n\nThis update includes the following packages:\n\n* Botkit v4.5.0\n* generator-botkit v4.5.0\n* [botbuilder-adapter-web v1.0.4](packages/botbuilder-adapter-web/CHANGELOG.md#104)\n* [botbuilder-adapter-slack v1.0.4](packages/botbuilder-adapter-slack/CHANGELOG.md#104)\n* [botbuilder-adapter-webex v1.0.2](packages/botbuilder-adapter-webex/CHANGELOG.md#102)\n* [botbuilder-adapter-facebook v1.0.4](packages/botbuilder-adapter-facebook/CHANGELOG.md#104)\n* [botbuilder-adapter-hangouts v1.0.3](packages/botbuilder-adapter-hangouts/CHANGELOG.md#103)\n* [botbuilder-adapter-twilio-sms v1.0.2](packages/botbuilder-adapter-twilio-sms/CHANGELOG.md#102)\n* [botkit-plugin-cms v1.0.2](packages/botkit-plugin-cms/CHANGELOG.md#102)\n\n----\n\n# 4.0.2\n\n* Added `disable_console` option to controller. When set to true, Botkit will not emit normal console output.\n* Fix Typerscript signature of controller.spawn() - Thanks to [@naktibalda](https://github.com/Naktibalda) for [the fix](https://github.com/howdyai/botkit/pull/1648)\n* Fix for allowing typing messages in dialogs - [Details](https://github.com/howdyai/botkit/issues/1646)\n* Remove useless try/catch blocks -  - Thanks to [@naktibalda](https://github.com/Naktibalda) for [the fix](https://github.com/howdyai/botkit/pull/1654)\n* Fix an issue where the convo.before hook would not fire as expected when looping a thread. \n\nCoinciding with 4.0.2, the adapters and plugin have also been updated with bug fixes and minor updates:\n\n* [botbuilder-adapter-web v1.0.3](packages/botbuilder-adapter-web/CHANGELOG.md#103)\n* [botbuilder-adapter-slack v1.0.3](packages/botbuilder-adapter-slack/CHANGELOG.md#103)\n* [botbuilder-adapter-webex v1.0.1](packages/botbuilder-adapter-webex/CHANGELOG.md#101)\n* [botbuilder-adapter-facebook v1.0.3](packages/botbuilder-adapter-facebook/CHANGELOG.md#103)\n* [botbuilder-adapter-hangouts v1.0.2](packages/botbuilder-adapter-hangouts/CHANGELOG.md#102)\n* [botbuilder-adapter-twilio-sms v1.0.1](packages/botbuilder-adapter-twilio-sms/CHANGELOG.md#101)\n* [botkit-plugin-cms v1.0.1](packages/botkit-plugin-cms/CHANGELOG.md#101)\n\n# Sub-package release notes\n\n* [botbuilder-adapter-web v1.0.2](packages/botbuilder-adapter-web/CHANGELOG.md#102)\n* [botbuilder-adapter-slack v1.0.2](packages/botbuilder-adapter-slack/CHANGELOG.md#102)\n\n# 4.0.1\n\nThis is the first major release of the new version of Botkit!\n\n* The same `hears()`, `says()` and `ask()` syntax you know and love, but now with modern Javascript conventions like async/await.\n* New capabilities like [interruptions](https://botkit.ai/docs/v4/core.html#interruptions) and [composable dialogs](https://botkit.ai/docs/v4/conversations.html#composing-dialogs).\n* All new platform adapters for Web chat, Slack, Webex, Facebook, Google Hangouts and Twilio SMS.\n* Built-in support for [Microsoft Bot Framework](https://dev.botframework.com) features like:\n    * Support for the [Bot Framework Emulator](http://aka.ms/botframework-emulator)\n    * Support for [Dialogs](https://npmjs.com/package/botbuilder-dialogs)\n    * Support for [Azure Bot Service](https://azure.microsoft.com/en-us/services/bot-service/)\n* Long awaited fixes and improvements like:\n    * Multi-page support for Facebook\n    * Conversation state persistence between across app nodes / app restarts\n    * Full Typescript support\n\nThe [all new docs for Botkit 4 can be found here](https://botkit.ai/docs/v4).\nAll of the [Glitch starter kits have been updated with the latest version](https://glitch.com/botkit).\n\nThe best way to get started with 4.0 is to boot up a brand new bot using the [Yeoman generator](https://npmjs.com/package/generator-botkit), and connect it to the [Bot Framework Emulator](http://aka.ms/botframework-emulator).\nYou'll be chatting with your new bot in minutes!\n\n```javascript\nnpm install -g yo botkit\nyo botkit\n```\n\n# 0.7.4\n\n* only require simple_storage when used: [#1566](https://github.com/howdyai/botkit/pull/1566)\n* Slack: [Extend support of blocks](https://github.com/howdyai/botkit/pull/1597) - Thanks to [@ihorrusinko](https://github.com/ihorrusinko)\n* Slack: [Add new block_actions events](https://github.com/howdyai/botkit/pull/1596) - Thanks to [@makstaks](https://github.com/makstaks)\n* [Updated docs for using blocks with Slack](https://botkit.ai/docs/readme-slack.html#interactive-messages) - Thanks to [@makstaks](https://github.com/makstaks)\n\n# 0.7.3\n\n* Slack: Messages can now contain a `blocks` field to support Slack's new [Block Kit feature](https://api.slack.com/reference/messaging/blocks). Thanks to [@ihorrusinko for this update](https://github.com/howdyai/botkit/pull/1594).\n* Slack: [set useQuerystring to true in Slack API](https://github.com/howdyai/botkit/pull/1547)\n* Slack: [Change 500 webserver status to 404 when team not found](https://github.com/howdyai/botkit/pull/1548)\n* Google Hangouts: [allow to consume auth data from env var instead of file](https://github.com/howdyai/botkit/pull/1543)\n* Pull requests will now trigger Travis builds\n\n\n# 0.7.2\n\nUpdate dependency on `request` to latest to fix security warnings in dependency tree.\n\n# 0.7.1\n\nUpdate dependency on `botbuilder` to `3.16` to fix security warnings in dependency tree.\n\n# 0.7.0\n\nThis release is the first major step towards [deprecating Botkit Studio](https://github.com/howdyai/botkit/issues/1534),\nand introducing a more general system for scripted dialogs and content from [Botkit CMS](https://github.com/howdyai/botkit-cms).\n\nWe urge all Botkit users to update to the most recent version of Botkit. This may require an update to your project's package.json file.\n\n* Remove all functionality pertaining to Botkit Studio statistics and analytics APIs. All stats related services provided by Botkit Studio will cease operation on Dec 15.\n* Remove `stats_optout` flag from configuration.\n* Remove Botkit Studio options from command line interface.\n* Calls to Botkit Studio and/or Botkit CMS will no longer include the user's id\n\nNew features and changes:\n\n* Support for Facebook Personas API. [Full docs here](https://botkit.ai/docs/readme-facebook.html#personas-api) -- [Thanks to @ouadie-lahdioui](https://github.com/howdyai/botkit/pull/1497)!\n* Many Facebook APIs [have been promisified](https://github.com/howdyai/botkit/pull/1520) by @htaidirt\n* Improved technique used to verify incoming webhooks from Slack [use hmac compare instead of direct compare](https://github.com/howdyai/botkit/pull/1539) - Thanks, @danhofer!\n# 0.6.21\n\n* Add support for Slack's chat.getPermalink\n\n# 0.6.20\n\n* Fix bug introduced in 0.6.19 that caused events to improperly fire twice.\n* Emit a warning if Slack webhook validation is not enabled.\n* To prepare for upcoming changes to Botkit Studio and Botkit stats collection:\n    * Prevent bots without Botkit Studio credentials from sending stat events\n    * Emit a message about stats data collection at startup\n\n# 0.6.19\n\nNo new features, but updates throughout the dependency tree for security and stability purposes.\n\n* Updated dependency versions to latest available\n\n* Rewrote Botkit command line tool to remove dependency on abandoned library. Upgrade to the latest: `npm install -g botkit`\n\n* Switched from using jscs to eslint for linting purposes.\n\n# 0.6.18\n\n* Fix syntax error in Web connector. Oops! Thanks for reporting this issue @iworkforthem!\n\n* Add support for Google Hangouts \"card_clicked\" event. [Thanks to @ouadie-lahdioui](https://github.com/howdyai/botkit/pull/1487)\n\n# 0.6.17\n\nIn addition to minor fixes, dependency version updates, and documentation updates, this version includes:\n\n* Google Hangouts support is here! Thanks to [@ouadie-lahdioui's hard work](https://github.com/howdyai/botkit/pull/1414), your bot can now operate in [Hangouts Chat](https://gsuite.google.com/products/chat/).\n\n    Get started with the [Botkit Starter Kit for Google Hangouts](https://github.com/howdyai/botkit-starter-googlehangouts).\n\n    [Botkit docs for Google Hangouts connector](https://botkit.ai/docs/readme-google-hangouts.html)\n\n* CiscoSpark bots are now officially WebexBots. Everything is backwards compatible thanks to the hard work of [@ObjectIsAdvantag](https://github.com/howdyai/botkit/pull/1349), but you should move to using `Botkit.webexbot()` instead of `Botkit.sparkbot()` ASAP.\n\n    [Botkit docs for Cisco Webex Teams](https://botkit.ai/docs/readme-webex.html)\n\n    [Read more about these changes](https://botkit.ai/docs/readme-webex.html#webex-rebrand).\n\n* Tests have been reorganized and updated thanks to [@fastbean-au](https://github.com/howdyai/botkit/pull/1468).\n\n* Errors that occur in the middleware pipeline will now cause `pipeline_error` event to be emitted. In addition, errors at specific stages of the pipeline will also emit their own events: `ingest_error`, `normalize_error`, `categorize_error` and `receive_error`. This should make it easier to debug problems in middleware. Thanks to [@Nop0x](https://github.com/howdyai/botkit/pull/1425).  [Docs](https://botkit.ai/docs/core.html#middleware-error-events)\n\n    Handle a pipeline error:\n    ```javascript\n    controller.on('pipeline_error', function(err, bot, message, stage_name) {\n        // ... handle it!\n    });\n    ```\n\n    Handle a specific stage error:\n    ```javascript\n    controller.on('ingest_error', function(err, bot, message) {\n        // ... handle it!\n    });\n    ```\n\n\n# 0.6.16\n\n* Fixed issue in Cisco adapter introduced in 0.6.15\n\n# 0.6.15\n\n* [The documentation has moved to a dedicated docs site!](https://botkit.ai/docs) The transition begun 3 versions ago is now complete. [Any future changes to documentation should be submitted to this repo](https://github.com/howdyai/botkit-docs).\n\nSome minor tweaks:\n\n* Update to the way Webex Teams bots identify themselves [PR #1397](https://github.com/howdyai/botkit/pull/1397) Thank you to @jpjpjp\n\n* Externalize the utterances object [#1085](https://github.com/howdyai/botkit/pull/1085) thanks to @hannanabdul55\n\n* For Botkit web adapter, add `typingDelayFactor` config option, as well as `controller.setTypingDelayFactor()` to change how fast the bot types. Values between 0-1 will speed up the bot's typing, values above 1 will slow it down. - [Docs](https://botkit.ai/docs/readme-web.html#controllersettypingdelayfactordelayfactor) - [PR #1387](https://github.com/howdyai/botkit/pull/1387) Thanks to @schmitzl\n\nSeveral updates to the TypeScript definitions:\n\n* Add `collectResponse` to CoreBot's public types [#1358](https://github.com/howdyai/botkit/pull/1358) thanks to @pducks32\n* Add missing methods to d.ts [#1359](https://github.com/howdyai/botkit/pull/1359) thanks to @ypresto\n* Updating typings for interactive messages [#1318](https://github.com/howdyai/botkit/pull/1318) thanks to @jaalger\n\nThanks to frequent contributor @ouadie-lahdioui for the updates to Facebook Messenger:\n\n* Add FB scheduled broadcast - [Docs](https://botkit.ai/docs/readme-facebook.html#cancel-a-scheduled-broadcast) - [#1354](https://github.com/howdyai/botkit/pull/1354)\n* Add FB payment settings API - [Docs](https://botkit.ai/docs/readme-facebook.html#controllerapimessenger_profilepayment_settings) - [#1369](https://github.com/howdyai/botkit/pull/1369)\n* Add FB Thread owner API - [Docs](https://botkit.ai/docs/readme-facebook.html#get-thread-owner) - [#1353](https://github.com/howdyai/botkit/pull/1353)\n\nSupport for Slack's new security feature:\n\n* Request Signing with Slack Signing Secret - [Docs](https://botkit.ai/docs/readme-slack.html#securing-outgoing-webhooks-and-slash-commands) - [#1406](https://github.com/howdyai/botkit/pull/1406) thanks to @shishirsharma\n\n\n# 0.6.14\n\n* Fix for require_delivery option in Facebook bots. [PR #1312](https://github.com/howdyai/botkit/pull/1312)\n\n* Errors encountered during Slack RTM connection process will now be reported to the callback function [PR #1335](https://github.com/howdyai/botkit/pull/1335)\n\n* Updated methodology used to validate email addresses when restricting access to Cisco Spark bots\n\n* Updated dependencies to latest stable versions\n\n\n\n# 0.6.13\n\n* Fix bugs and refactor handling of message actions, particularly as they relate to Botkit Studio scripts\n\n* Adjust mechanism used to construct facebook quick reply payload in order to support future formats. [PR #1301](https://github.com/howdyai/botkit/pull/1301)\n\n* Promisify Facebook Messenger profile API. [PR #1300](https://github.com/howdyai/botkit/pull/1300)\n\n* Lower the log priority from 'log' to 'debug' for several messages in Botkit Core and Botkit Slack.\n\n\n# 0.6.12\n\n* [Botkit has a brand new docs site!](https://botkit.ai/docs) We have begun transitioning the documentation out of this repo into a [dedicated documentation repo](https://github.com/howdyai/botkit-docs).\n\n* Remove dependency on Python introduced in 0.6.10.  Thanks to @qiongfangzhang for the attention on that!\n\n* Fix for Facebook Messenger send broadcast function. [PR #1280](https://github.com/howdyai/botkit/pull/1280) Thanks @OmranAbazid\n\n* Extend Facebook's user profile object with locale. [PR #1265](https://github.com/howdyai/botkit/pull/1265) Thanks @julianusti\n\n* Added 'picture' to Facebook User Profile endpoint. [PR #1264](https://github.com/howdyai/botkit/pull/1264) Thanks @se\n\n* Add FB request thread control [PR #1257](https://github.com/howdyai/botkit/pull/1257) Thanks as always to @ouadie-lahdioui\n\n* Remove requirement that Cisco Spark endpoint be SSL. [PR #1284](https://github.com/howdyai/botkit/pull/1284) thanks @akalsey and your beard.\n\n* Add support for Slack's `users.lookupByEmail` API. [PR #1285](https://github.com/howdyai/botkit/pull/1285)\nThanks to @piglovesyou\n\n* Fix to the way variables are copied between conversations while using Botkit Studio scripts\n\n# 0.6.11\n\n* For Botkit Studio users, added `controller.studio.getById()` for loading scripts\nby their unique ID rather than by name or trigger. [Docs here](docs/readme-studio.md#controllerstudiogetbyid)\n\n# 0.6.10\n\n* Add support for Cisco Jabber. Thanks to @qiongfangzhang and @panx981389 and their team at Cisco for the contribution!\n\n[Documentation for the Cisco Jabber adapter can be found here](docs/readme-ciscojabber.md)\n\n* Updated `ciscospark` dependency to latest version and fixed some bugs in the example bot\n\n* Update Twilio dependency to latest, along with small updates to adapter. Thanks @nishant-chaturvedi! [PR #1140](https://github.com/howdyai/botkit/pull/1140)\n\n# 0.6.9\n\n* Add 2 new middleware endpoints that occur during conversations - `conversationStart(bot, convo, next)` and `conversationEnd(bot, convo, next)`.  [Some new documentation](docs/readme.md#conversation-events-and-middleware-endpoints)\n* Conversations powered by Botkit Studio will now include `convo.context.script_name` and `convo.context.script_id` which point back to the script loaded from the Botkit Studio API\n* When using Botkit Studio's execute script action, the resulting conversation object will have 2 additional context fields: `convo.context.transition_from` and `convo.context.transition_from_id` which will point to the script from which the user transitioned\n* When using Botkit Studio's execute script action, the original conversation from which the user is transitioning will have 2 additional context fields: `convo.context.transition_to` and `convo.context.transition_to_id` which will point to the script to which the user transitioned\n* Fix for Botkit Studio scripts which used \"end and mark successful\" action from a condition. Previously this would end, but not mark successful.\n\nMerged Pull Requests:\n* Make sure Facebook API errors are passed to callback if specified [PR #1225](https://github.com/howdyai/botkit/pull/1225)\n* Refresh Microsoft Teams token when it has expired. [PR #1230](https://github.com/howdyai/botkit/pull/1230)\n* Update TypeScript definition for Web bots [PR #1231](https://github.com/howdyai/botkit/pull/1231)\n* Update TypeScript definition for bot.replyAndUpdate [PR #1232](https://github.com/howdyai/botkit/pull/1232)\n* Fix for Microsoft teams button builder function [PR #1233](https://github.com/howdyai/botkit/pull/1233)\n\n# 0.6.8\n\nBIG UPDATE:\n\n[Botkit now works on the web!](docs/readme-web.md) The new web connector supports websocket and webhook connections for sending and receiving messages. The brand new [Botkit Anywhere starter kit](https://github.com/howdyai/botkit-starter-web) includes a [customizable web chat client](https://github.com/howdyai/botkit-starter-web/blob/master/docs/botkit_web_client.md), and a [built-in chat server](https://github.com/howdyai/botkit-starter-web/blob/master/docs/botkit_chat_server.md).  Of course, this works with the existing stack of Botkit tools and plugins!\n\nNew for Botkit Studio:\n\nDevelopers using Botkit Studio to create and manage script content can now utilize a new message action in their conditional statements, or at the end of any thread.\nIt is now possible to direct your bot to seamlessly transition to a different Botkit Studio script. This allows for new patterns like interconnected menus, loops and branching conversations.\n\nNew core features:\n\nDevelopers can now exclude specific types of events from being included in conversations using `controller.excludeFromConversations(event_name)`.\nThis has been applied to the Facebook connector, which will now exclude certain events automatically. [Docs](docs/readme.md#excluding-events-from-conversations)\n\nThe tick interval used for driving conversations can now be adjusted using `controller.setTickDelay(ms)`.  [Docs](docs/readme.md#changing-the-speed-of-botkits-internal-tick)\n\n\nMerged pull requests:\n\nOur community of Botkit Core developers is more than 150 people strong! Thank you to all of the contributors who spent their precious time improving Botkit for everyone. There are more than a dozen pull requests included in this release!!\n\nCore:\n\n* Upgraded the `ws` dependency to latest - [Thanks @naktibalda](https://github.com/howdyai/botkit/pull/1154)\n* Add delete method to in-memory store - [Thanks @naktibalda](https://github.com/howdyai/botkit/pull/1164)\n* memory store: don't log warning after each save - [Thanks @naktibalda](https://github.com/howdyai/botkit/pull/1197)\n\nFacebook:\n\nThis release contains a ton of updates to the Facebook connector, many of which were contributed by @ouadie-lahdioui!\n\n* pass error object to the callbacks for failed send Api calls - [Thanks @nishant-chaturvedi](https://github.com/howdyai/botkit/pull/1147)\n* Secures FB Graph API Requests with optional app secret [Docs](docs/readme-facebook.md#app-secret-proof) - [Thanks @ouadie-lahdioui](https://github.com/howdyai/botkit/pull/1170)\n* Add Facebook Handover Protocol [Docs](docs/readme-facebook.md#handover-protocol) - [Thanks @ouadie-lahdioui](https://github.com/howdyai/botkit/pull/978)\n* Include messaging_type property in all Botkit message sends [Docs](docs/readme-facebook.md#messaging-type)- [Thanks @ouadie-lahdioui](https://github.com/howdyai/botkit/pull/1171)\n* Add FB Broadcast Messages API [Docs](https://github.com/howdyai/botkit/blob/068/docs/readme-facebook.md#broadcast-messages-api) - [Thanks @ouadie-lahdioui](https://github.com/howdyai/botkit/pull/1180)\n* Add Facebook insights API [Docs](https://github.com/howdyai/botkit/blob/068/docs/readme-facebook.md#messaging-insights-api) - [Thanks @ouadie-lahdioui](https://github.com/howdyai/botkit/pull/1183)\n* Include user's email in profile if returned from facebook API - [Thanks @iniq](https://github.com/howdyai/botkit/pull/1193)\n* Properly trigger security session events from facebook workplace - [Thanks @ariel-learningpool](https://github.com/howdyai/botkit/pull/1110)\n* fix bug when using Facebook Checkbox Plugin - [Thanks @shmuelgutman](https://github.com/howdyai/botkit/pull/1101)\n\nBotkit will now exclude `message_delivered`, `message_echo` and `message_read` events from inclusion in conversations using the new `excludeFromConversations()` function. [Docs](docs/readme.md#excluding-events-from-conversations)\n\n\nSlack:\n\nThese fixes for the Slack connector add more ways to protect your bot from potentially malicious incoming webhook events. Use them!!\n\n* Add optional Slack token verification to config - [Thanks @shishisharma](https://github.com/howdyai/botkit/pull/981)\n* Apply verification middleware only on the webhook endpoint - [Thanks @nishant-chaturvedi](https://github.com/howdyai/botkit/pull/1203)\n\n# 0.6.7\n\nAdd `controller.studio.getScripts()` to load all a list of available scripts from Botkit Studio [Docs](docs/readme-studio.md#controllerstudiogetscripts)\n\nAdd handling (and error messages) for 401 response codes from Botkit Studio APIs that indicate a bad access token\n\n## 0.6.6\n\nImportant fixes to Facebook and Cisco Spark connectors: A breaking change was introduced in 0.6.5 which has now been fixed.\n\nRemove `crypto` dependency, now use built-in crypto library.\n\nUpdate `botkit-studio-sdk` dependency to latest version.\n\n## 0.6.5\n\nIntroducing the Botkit command line tool!\n\nRun: `npm install -g botkit`\n\nThen, you'll be able to set up a new Botkit project (based on one of our excellent starter kits!) by typing:\n\n`botkit new --name \"my bot\"`\n\nNew helper functions:\n\nBotkit bots for Slack, Cisco Spark, Microsoft Teams and Facebook now have support for additional helper functions:\n\n`bot.getMessageUser(message)` returns a Promise that will receive a normalized user profile object for the user who sent the message.\n\n`bot.getInstanceInfo()` returns a Promise that will receive a normalized instance object, with `identity` and `team` fields.\n\n\n## 0.6.4\n\nFix for Cisco Spark: improved methodology for detecting and handling @mentions\n\nFix for Slack: allow multiple validation errors to be passed in to `bot.dialogError()`.  Thanks @cfs! [PR #1080](https://github.com/howdyai/botkit/pull/1080)\n\nFix for Slack: fix for `bot.whisper()` Thanks to @jonchurch and @fletchrichman!\n\nNew: Botkit Studio scripts may now contain custom fields in message objects. This is in support of an upcoming feature in Botkit Studio which will allow developers to add define these custom fields in the Studio IDE.\n\n## 0.6.3\n\nNew: Support for [Slack Dialogs](https://api.slack.com/dialogs), including:\n\n* `bot.createDialog()` function [Docs](docs/readme-slack.md#dialogs)\n* `bot.replyWithDialog()` function [Docs](docs/readme-slack.md#botreplywithdialog)\n* `bot.api.dialog.open()` function\n* `dialog_submission` event [Docs](docs/readme-slack.md#receive-dialog-submissions)\n* `bot.dialogOk()` function [Docs](docs/readme-slack.md#botdialogok)\n* `bot.dialogError()` function [Docs](docs/readme-slack.md#botdialogerror)\n\nFix: Cisco Spark bots will once again receive `direct_message` and `direct_mention` events. (Fix for [#1059](https://github.com/howdyai/botkit/issues/1059))\n\n## 0.6.2\n\nFix bug in Facebook connector: call `startTicking()` as part of object instantiation. This was missing in 0.6 and 0.6.1\n\nMove call to `startTicking()` in TwilioIPM connector to make it consistent with other connectors.\n\nFix: Catch 202 response code that does not have a JSON response body. This status sometimes comes back from the MS Teams API when a message has been queued for delivery.\n\n## 0.6.1\n\nFix bugs in Botframework and ConsoleBot connectors that caused messages not to send. Resolves #1033.\n\nFix typo in Twilio connector that caused attached media to fail. Thanks @jpowers! [PR #1023](https://github.com/howdyai/botkit/pull/1023)\n\nFix missing `bodyParser` module in Facebook connector. Resolves #1041.\n\nNew: Add support for the new `conversations` APIs for Slack. [Read about this new API here](https://api.slack.com/docs/conversations-api).\n\nNew: Add `usergroups` APIs for Slack. Thanks to @digitalspecialists for this! [PR #1001](https://github.com/howdyai/botkit/pull/1001)\n\nChange: Facebook `message_echo` webhooks will now emit `message_echo` events instead of `message_received` events to distinguish them from messages sent by users.\n\n\n## 0.6.0\n\nThis version features some BIG CHANGES!\n\n**New platform support:**\n\n[Microsoft Teams](docs/readme-teams.md) is now officially supported with its own connector, including new features in [Botkit Studio](https://studio.botkit.ai) like authoring of Teams-specific attachments, an app package builder and configuration manager, and [a new starter kit](https://github.com/howdyai/botkit-starter-teams).\n\n[Read the full docs for Botkit for Microsoft Teams](docs/readme-teams.md)\n\n**Major changes to message handling code:**\n\n[Introducing the Botkit Message Pipeline](docs/readme-pipeline.md), a formalized process for Botkit's handling of incoming and outgoing messages. All of the platform connectors have been refactored to use this new series of middleware functions, and are now implemented in a uniform way.\n\nDevelopers who make use of Botkit's middleware system should [take time to read this update](docs/readme-pipeline.md). Most current middleware functions will  continue to work as expected, but mild changes may be desirable to update these functions to use Botkit's latest features.\n\nIn addition, developers who use third party middleware plugins should carefully retest their applications after upgrading to version 0.6, as these plugins may need to be updated for full compatibility.\n\n**Upgrade Guide:**\n\nThis version of Botkit deprecates the `receive_via_postback` and `interactive_replies` options\nthat caused button clicks to be treated as typed messages.  These and other small changes to the way Botkit emits events may require minor updates to some Botkit apps.\n\n[Upgrading from Botkit 0.5 or lower? Read this guide!](docs/howto/upgrade_05to06.md)\n\n\n## 0.5.8\n\nSlack: Support for sending ephemeral messages with `bot.whisper()` and `bot.sendEphemeral()`. In addition, any message with `message.ephemeral` set to true will be sent with `bot.sendEphemeral()` automatically. [Read documentation here.](docs/readme-slack.md#ephemeral-messages) Thanks to [@jonchurch](https://github.com/howdyai/botkit/pull/958)\n\nSlack: Add support for `bot.api.files.sharedPublicURL()` method. Thanks to [@GitTristan](https://github.com/howdyai/botkit/pull/912)\n\nFacebook: Support for using [message tags](https://developers.facebook.com/docs/messenger-platform/message-tags).  [Read documentation here.](docs/readme-facebook.md#message-tags) Thanks to [@ouadie-lahdioui](https://github.com/howdyai/botkit/pull/960)\n\nFacebook: Support for using Facebook's new built-in NLP tools. [Read documentation here.](docs/readme-facebook.md#built-in-nlp) Thanks to [@ouadie-lahdioui](https://github.com/howdyai/botkit/pull/943) for this one too!!\n\n\nTwilio SMS: Add support for sending MMS messages (file attachments) via Twilio. [Read documentation here.](docs/readme-twiliosms.md#sending-media-attachments-mms) Thanks to [@krismuniz](https://github.com/howdyai/botkit/pull/951)!\n\nCisco Spark: Emit a console warning when a bot receives messages from outside the allowed domain list. Thanks to [@MathRobin](https://github.com/howdyai/botkit/pull/918)!\n\nNew: Typescript declarations! Thanks to [@uny and @naktibalda](https://github.com/howdyai/botkit/pull/953) for their work on this.\n\n\n\n## 0.5.7\n\nLock in ciscospark dependency at version 1.8.0 until further notice due to breaking changes in more recent versions.\n\n## 0.5.6\n\nFix for Botkit Studio-powered bots: Facebook attachments can now be added without buttons\n\nFix for Cisco Spark: Bot mentions will now reliably be pruned from message, regardless of what client originated the message\n\nFix for Cisco Spark: startPrivateConversationWithPersonID has been fixed.\n\n## 0.5.5\n\n*Introducing Botkit for SMS!* Botkit bots can now send and receive messages using Twilio's Programmable SMS API!\nHuge thanks to @krismuniz who spearheaded this effort! [Read all about Twilio SMS here](docs/readme-twiliosms.md)\n\n*New unit tests* have been added, thanks to the ongoing efforts of @colestrode, @amplicity and others.\nThis release includes coverage of the Botkit core library and the Slack API library.\nThis is an [ongoing effort](https://github.com/howdyai/botkit/projects/3), and we encourage interested developers to get involved!\n\nAdd missing error callback to catch Slack condition where incoming messages do not match a team in the database.\n[PR #887](https://github.com/howdyai/botkit/pull/887) thanks to @alecl!\n\nAdd support for Facebook attachment upload api [PR #899](https://github.com/howdyai/botkit/pull/899) thanks @ouadie-lahdioui!\nRead docs about this feature [here](docs/readme-facebook.md#attachment-upload-api)\n\nFixed issue with Slack message menus. [PR #769](https://github.com/howdyai/botkit/pull/769)\n\nFixed confusing parameter in JSON storage system. `delete()` methods now expect object id as first parameter. [PR #854](https://github.com/howdyai/botkit/pull/854) thanks to @mehamasum!\n\nAll example bot scripts have been moved into the [examples/](examples/) folder. Thanks @colestrode!\n\nFixes an instance where Botkit was not automatically responding to incoming webhooks from Cisco with a 200 status. [PR #843](https://github.com/howdyai/botkit/pull/843)\n\nUpdated dependencies to latest: twilio, ciscospark, https-proxy-agent, promise\n\n## 0.5.4\n\nFix for [#806](https://github.com/howdyai/botkit/issues/806) - new version of websocket didn't play nice with Slack's message servers\n\nSupport for Slack's new [rtm.connect method](https://api.slack.com/methods/rtm.connect).\n\nUse rtm.connect instead of rtm.start when connecting an RTM bot to Slack. This should performance during connections.\n\n## 0.5.3\n\nAdd a new [readme file](readme.md) and moved other documentation into `docs/` folder.\n\nUpdate all dependencies to their most recent versions\n\nChange behavior of conversation timeouts. [New behavior is documented here.](docs/readme.md#handling-conversation-timeouts)\n\nSupport for Facebook Messenger's new \"Home URL\" setting [PR #793](https://github.com/howdyai/botkit/pull/793)\n[New features documented here.](https://github.com/howdyai/botkit/blob/master/docs/readme-facebook.md#controllerapimessenger_profilehome_url)\n\nSupport for including parameters in Facebook codes. [PR #790](https://github.com/howdyai/botkit/pull/790)\n[Docs here.](https://github.com/howdyai/botkit/blob/master/docs/readme-facebook.md#messenger-code-api)\n\nSupport for Facebook's new \"target audience\" APIs [PR #798](https://github.com/howdyai/botkit/pull/798)\n\nSupport for additional Slack user APIs, including 'user.profile.set' and 'user.profile.get'. [PR #780](https://github.com/howdyai/botkit/pull/780)\n\nAdd support for `createPrivateConversation()` in Slack bots [PR #586](https://github.com/howdyai/botkit/pull/586)\n\n*beforeThread Hooks:*\n\nThese new hooks allow developers to execute custom functionality as a conversation transitions from one thread to another.\nThis enables asynchronous operations like database and API calls to be made mid-conversation, and can be used to add additional\ntemplate variables (using `convo.setVar()`), or change the direction of the conversation (using `convo.gotoThread()`).\n\nAdd `convo.beforeThread()`, a plugin hook that fires before a conversation thread begins. [Docs](docs/readme.md#convobeforethread)\n\nAdd `controller.studio.beforeThread()`, a plugin hook that fires before a Botkit Studio-powered conversation thread begins. [Docs](docs/readme-studio.md#controllerstudiobeforethread)\n\n\n## 0.5.2\n\n*Changes for Slack:*\n\nAdd support for Slack's new `chat.unfurl` method for use with [App Unfurls](https://api.slack.com/docs/message-link-unfurling)\n\nAdd additional Slack's team API methods [PR #677](https://github.com/howdyai/botkit/pull/677)\n\nBotkit will now store the value of the state parameter used in the oauth flow in the team's record [PR #657](https://github.com/howdyai/botkit/pull/657)\n\nFixes slash commands when using internal webserver [PR #699](https://github.com/howdyai/botkit/pull/699)\n\nAdd error logging for say and spawn.run [PR #691](https://github.com/howdyai/botkit/pull/691)\n\n*Changes for Facebook Messenger:*\n\nUpdates to Facebook's Messenger Profile APIs (previously thread settings APIs) [PR #690](https://github.com/howdyai/botkit/pull/690)\n\nAdd ability to retrieve Messenger Code image [PR #689](https://github.com/howdyai/botkit/pull/689)\n\nAdd support for Facebook's domain whitelisting API [PR #573](https://github.com/howdyai/botkit/pull/573)\n\nAdd tests for handleWebhookPayload in Facebook bot flow [PR #678](https://github.com/howdyai/botkit/pull/678)\n\nAdd Facebook account linking support [PR #578](https://github.com/howdyai/botkit/pull/578)\n\nAdd ability to customize api url for Facebook [PR #576](https://github.com/howdyai/botkit/pull/567)\n\n*Changes to Botkit Core:*\n\nAdd \"done\" and \"exit\" as a utterances for \"quit\" [PR #498](https://github.com/howdyai/botkit/pull/498)\n\n*Thanks*\n\nThanks to @jhsu @davidwneary @mbensch @alecl @ouadie-lahdioui @agamrafaeli @katsgeorgeek @jfairley\n\n\n## 0.5.1\n\nFixes for Cisco Spark:\n\nAllow port number to be included in public_address\n\nFix to issue when using retrieveFile()\n\nFixes for Slack:\n\nAdd support for `channel.replies` API\n\nFixes for Facebook:\n\nAdd support for [Facebook account linking](https://github.com/howdyai/botkit/pull/645)\n\n## 0.5.0\n\nAdd support for bots on [Cisco Spark](http://developer.ciscospark.com)! For information about getting started, and to learn about new Botkit features that are specific to this platform, [check out our new Cisco Spark readme. ](readme-ciscospark.md)\n\nBotkit will now send a user agent header on all requests to the Slack API\n\nWhen building for Slack, developers may now override the root URL of the API by specifying `api_root` in the configuration in order to use mocked testing endpoints or use the Slack API through a proxy.\n\n## 0.4.10\n\nAdd support for [Slack Enterprise Grid](https://slack.com/enterprise), for more information [read](https://blog.howdy.ai/beam-us-up-botkit-in-the-enterprise-e6133e0cbdf3#.o3md9lw29)\n\nAdd Support for Slack's new thread system, including:\n\n[bot.replyInThread()](readme-slack.md#botreplyinthread) to create a threaded reply\n\n[bot.startConversationInThread()](readme-slack.md#botstartconversationinthread) to create and immediately start a conversation in a thread\n\n[bot.createConversationInThread()](readme-slack.md#botcreateconversationinthread) to create a conversation in a thread\n\nAdd new `heard` middleware endpoint, which fires _after_ a pattern has been matched, but before the handler function is called. This allows developers to enrich messages with NLP tools or other plugins, but do so only when the original message matches specific criteria.\n\nAdd new `capture` middleware endpoint, which fires _after_ a user responds to a `convo.ask` question but _before_ the related handler function is called. This allows developers to change the value that is captured, or capture additional values such as entities returned by an NLP plugin.\n\n\n## 0.4.9\n\n`controller.version()` will now report the currently installed version of Botkit.\n\nChange to how quick replies are rendered via Botkit Studio's API\n\n## 0.4.7\n\nAdd support for Facebook Messenger \"location\" quick replies [PR #568](https://github.com/howdyai/botkit/pull/568)\n\nAdd support for Slack's new users.setPresence API [PR #562](https://github.com/howdyai/botkit/pull/562)\n\nAdd support for Slack's new reminders API [PR #580](https://github.com/howdyai/botkit/pull/580)\n\n\n\n## 0.4.6\n\nChange to controller.studio.runTrigger: Will now resolve promise regardless of whether a trigger was matched\n\n## 0.4.5\n\nBug fix: Fix detection of Slackbot interactive callbacks\n\n## 0.4.4\n\nChanges:\n\nAdd referral field to `facebook_postback` events, if set [PR #552](https://github.com/howdyai/botkit/pull/553)\n\nRefactor handling of incoming webhooks from Slack and Facebook in order to make it easier for developers to create custom endpoints and/or integrate Botkit into existing Express applications.\n\nAdd `controller.handleWebhookPayload()` to process a raw webhook payload and ingest it into Botkit\n\nMake stale connection detection configurable [PR #505](https://github.com/howdyai/botkit/pull/505)\n\nDDOS Vulnerability Fix - Secure Facebook Webhook [PR #555](https://github.com/howdyai/botkit/pull/555)\n\n\nBug fixes:\n\nFix an issue where a custom redirect_uri would be rejected by Slack's oauth verification\n\nFix bot_channel_join and bot_group_join with Slack Events API [PR #514](https://github.com/howdyai/botkit/pull/514)\n\nFix path to static content directory [PR #546](https://github.com/howdyai/botkit/pull/546)\n\n`retry` and `send_via_rtm` options are now properly associated with the controller object.\n\nFix some issues pertaining to typing indicators and the slack RTM [PR #533](https://github.com/howdyai/botkit/pull/533)\n\n\n\n\n## 0.4.3\n\nAdds [convo.transitionTo()](readme.md#convotransitionto), a new feature for creating smoother transitions between conversation threads\n\nAdds support for new Facebook Messenger [thread settings APIs](readme-facebook.md#thread-settings-api)\nwhich enable developers to set and manage the 'getting started' screen and persistent menus.\n\nAdds support for Facebook Messenger attachment in [Botkit Studio](https://studio.botkit.ai)\n\nAdds a check to ensure messages are properly received by Facebook and Slack before proceeding to next message in a conversation.\n\nAdds optional `require_delivery` option for Facebook and Slack bots which tells Botkit to wait to receive a delivery confirmation from the platform before sending further messages. [Slack info](readme-slack.md#require-delivery-confirmation-for-rtm-messages) [Facebook info](readme-facebook.md#require-delivery-confirmation)\n\nChange: Receiving `facebook_postback` events as normal \"spoken\" messages now requires the `{receive_via_postback:true}` option be set on the controller. [Read more](readme-facebook.md#receive-postback-button-clicks-as-typed-messages)\n\n## 0.4.2\n\nSupport for Slack's [Events API](https://api.slack.com/events-api) is here, thanks to the Botkit contributor community. [Read documentation here](https://github.com/howdyai/botkit/blob/master/readme-slack.md#events-api)\n\nBug fix:\n\nFixes an issue with setting the default IP address for the Express server introduced in 0.4.1\n\n## 0.4.1\n\nThis release contains many small fixes and updates to keep up with the ever changing platforms!\n\nBIG CHANGES:\n\nSlack bots will now send messages via the Web API instead of the RTM. This behavior can be changed by passing `send_via_rtm: true` to `controller.spawn()`\n\nAdds [ConsoleBot](lib/ConsoleBot.js) for creating bots that work on the command line\n\nAdds a new [Middleware Readme](readme-middlewares.md) for documenting the existing middleware modules\n\nAdds an example for using quick replies in the [Facebook Example Bot](examples/facebook_bot.js)\n\nAdds additional fields to Facebook messages to specify if they are `facebook_postback`s or normal messages.\n\nAdds optional `hostname` field to constructor functions to bind Express to a specific IP.\n\nFixes for Slack's files.upload API\n\nMerge in numerous pull requests from the community:\n[PR #461](https://github.com/howdyai/botkit/pull/461)\n[PR #465](https://github.com/howdyai/botkit/pull/465)\n[PR #466](https://github.com/howdyai/botkit/pull/466)\n[PR #469](https://github.com/howdyai/botkit/pull/469)\n[PR #472](https://github.com/howdyai/botkit/pull/472)\n[PR #474](https://github.com/howdyai/botkit/pull/474)\n[PR #434](https://github.com/howdyai/botkit/pull/434)\n[PR #435](https://github.com/howdyai/botkit/pull/435)\n[PR #440](https://github.com/howdyai/botkit/pull/440)\n[PR #441](https://github.com/howdyai/botkit/pull/441)\n[PR #443](https://github.com/howdyai/botkit/pull/443)\n[PR #446](https://github.com/howdyai/botkit/pull/446)\n[PR #448](https://github.com/howdyai/botkit/pull/448)\n\n\n## 0.4\n\nAdd support for Botkit Studio APIs. [More Info](readme-studio.md)\n\nSubstantially expanded the documentation regarding Botkit's [conversation thread system](readme.md#conversation-threads).\n\nAdd support for Microsoft Bot Framework.  The [Microsoft Bot Framework](https://botframework.com) makes it easy to create a single bot that can run across a variety of messaging channels including [Skype](https://skype.com), [Group.me](https://groupme.com), [Facebook Messenger](https://messenger.com), [Slack](https://slack.com),\n[Telegram](https://telegram.org/), [Kik](https://www.kik.com/), [SMS](https://www.twilio.com/), and [email](https://microsoft.office.com). [More Info](readme-botframework.md)\n\nUpdates to Facebook Messenger connector to support features like message echoes, read receipts, and quick replies.\n\nMerged numerous pull requests from the community:\n[PR #358](https://github.com/howdyai/botkit/pull/358)\n[PR #361](https://github.com/howdyai/botkit/pull/361)\n[PR #353](https://github.com/howdyai/botkit/pull/353)\n[PR #363](https://github.com/howdyai/botkit/pull/363)\n[PR #320](https://github.com/howdyai/botkit/pull/320)\n[PR #319](https://github.com/howdyai/botkit/pull/319)\n[PR #317](https://github.com/howdyai/botkit/pull/317)\n[PR #299](https://github.com/howdyai/botkit/pull/299)\n[PR #298](https://github.com/howdyai/botkit/pull/298)\n[PR #293](https://github.com/howdyai/botkit/pull/293)\n[PR #256](https://github.com/howdyai/botkit/pull/256)\n[PR #403](https://github.com/howdyai/botkit/pull/403)\n[PR #392](https://github.com/howdyai/botkit/pull/392)\n\n\n\nIn order to learn about and better serve our user community, Botkit now sends anonymous usage stats to stats.botkit.ai. To learn about opting out of stats collection, [read here](readme.md#opt-out-of-stats).\n\n## 0.2.2\n\nAdd support for Slack Interactive Messages.\n\nAdd example of Slack button application that provides a bot that uses interactive messages.\n\nNew functionality in Slack bot: Botkit will track spawned Slack bots and route incoming webhooks to pre-existing RTM bots. This enables RTM bots to reply to interactive messages and slash commands.\n\n## 0.2.1\n\nImproves Slack RTM reconnects thanks to @selfcontained [PR #274](https://github.com/howdyai/botkit/pull/274)\n\n## 0.2\n\nAdds support for Twilio IP Messaging bots\n\nAdd example bot: twilio_ipm_bot.js\n\n## 0.1.2\n\n*Slack changes:*\n\nAdds authentication of incoming Slack webhooks if token specified. [More info](readme_slack.md#securing-outgoing-webhooks-and-slash-commands) [Thanks to [@sgud](https://github.com/howdyai/botkit/pull/167)]\n\nImproves support for direct_mentions of bots in Slack (Merged [PR #189](https://github.com/howdyai/botkit/pull/189))\n\nMake the oauth identity available to the user of the OAuth endpoint via `req.identity` (Merged [PR #174](https://github.com/howdyai/botkit/pull/174))\n\nFix issue where single team apps had a hard time receiving slash command events without funky workaround. (closes [Issue #108](https://github.com/howdyai/botkit/issues/108))\n\nAdd [team_slashcommand.js](/examples/slack/team_slashcommand.js) and [team_outgoingwebhook.js](/examples/slack/team_outgoingwebhook.js) to the examples folder.\n\n\n\n*Facebook changes:*\n\nThe `attachment` field may now be used by Facebook bots within a conversation for both convo.say and convo.ask.  In addition, postback messages can now be received as the answer to a convo.ask in addition to triggering their own facebook_postback event. [Thanks to [@crummy](https://github.com/howdyai/botkit/pull/220) and [@tkornblit](https://github.com/howdyai/botkit/pull/208)]\n\nInclude attachments field in incoming Facebook messages (Merged [PR #231](https://github.com/howdyai/botkit/pull/231))\n\nAdds built-in support for opening a localtunnel.me tunnel to expose Facebook webhook endpoint while developing locally. (Merged [PR #234](https://github.com/howdyai/botkit/pull/234))\n\n## 0.1.1\n\nFix issue with over-zealous try/catch in Slack_web_api.js\n\n## 0.1.0\n\nAdds support for Facebook Messenger bots.\n\nRename example bot: bot.js became slack_bot.js\n\nAdd example bot: facebook_bot.js\n\n## 0.0.15\n\nChanges conversation.ask to use the same pattern matching function as\nis used in `hears()`\n\nAdds `controller.changeEars()` Developers can now globally change the\nway Botkit matches patterns.\n\n\n## 0.0.14\n\nAdd new middleware hooks. Developers can now change affect a message\nas it is received or sent, and can also change the way Botkit matches\npatterns in the `hears()` handler.\n\n## 0.0.~\n\nNext time I promise to start a change log at v0.0.0\n"
  },
  {
    "path": "lerna.json",
    "content": "{\n  \"packages\": [\n    \"packages/*\"\n  ],\n  \"version\": \"independent\"\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"botkit-packages\",\n  \"private\": true,\n  \"scripts\": {\n    \"postinstall\": \"lerna bootstrap --hoist\",\n    \"build\": \"lerna run build\",\n    \"test\": \"lerna run build ; lerna run test\",\n    \"build-docs\": \"lerna run build-docs\",\n    \"eslint\": \"./node_modules/.bin/eslint  ./packages/*/src/*.ts ./packages/*/src/**/*.ts\",\n    \"eslint-fix\": \"./node_modules/.bin/eslint  ./packages/*/src/*.ts ./packages/*/src/**/*.ts --fix\",\n    \"lerna:pack\": \"lerna run pack\"\n  },\n  \"devDependencies\": {\n    \"@typescript-eslint/eslint-plugin\": \"^5.16.0\",\n    \"@typescript-eslint/parser\": \"^5.16.0\",\n    \"eslint\": \"^8.11.0\",\n    \"eslint-config-standard\": \"^16.0.3\",\n    \"lerna\": \"^4.0.0\",\n    \"mocha\": \"^9.1.3\",\n    \"nyc\": \"^15.1.0\",\n    \"typescript\": \"^3.7.5\"\n  }\n}\n"
  },
  {
    "path": "packages/botbuilder-adapter-facebook/.eslintrc.js",
    "content": "module.exports = {\n    \"extends\": \"standard\",\n    \"rules\": {\n        \"semi\": [2, \"always\"],\n        \"indent\": [2, 4],\n        \"no-return-await\": 0,\n        \"camelcase\": 0,\n        \"no-unused-vars\": 0,\n        \"@typescript-eslint/indent\": 0,\n        \"@typescript-eslint/ban-ts-ignore\": 1,\n        \"@typescript-eslint/no-object-literal-type-assertion\": 0,\n        \"@typescript-eslint/explicit-member-accessibility\": 1,\n        \"space-before-function-paren\": [2, {\n            \"named\": \"never\",\n            \"anonymous\": \"never\",\n            \"asyncArrow\": \"always\"\n        }],\n        \"template-curly-spacing\": [2, \"always\"]\n    }\n};"
  },
  {
    "path": "packages/botbuilder-adapter-facebook/.gitignore",
    "content": "node_modules/\n.env\nlib/\n.nyc_output/\n"
  },
  {
    "path": "packages/botbuilder-adapter-facebook/CHANGELOG.md",
    "content": "# botbuilder-adapter-facebook changelog\n\n# 1.0.11\n\n* Update dependencies to Botkit 4.10, Bot Framework 4.10\n\n# 1.0.10\n\n* Update dependencies to Botkit 4.9, Bot Framework 4.9\n\n# 1.0.7\n\n* Fix for Facebook typing indicators. To send a typing indicator, use `await bot.say({sender_action: 'typing_on'});`\n\n# 1.0.6\n\n* Query parameters for GET apis can now be passed in using an object parameter (like POST): [Thanks to @adantoscano](https://github.com/howdyai/botkit/pull/1768)\n\n* Update dependencies (Bot Framework to 4.6, Botkit to 4.6)\n\n# 1.0.5\n\n* Properly export the facebook_api class so it can be used directly. Thanks to [@luckyluo](https://github.com/howdyai/botkit/pull/1766)!\n\n# 1.0.4\n\n* Update dependencies (Bot Framework to 4.5.2, Botkit to 4.5)\n* Fix for over-pruning of quick replies and attachments in dialogs\n\n# 1.0.3\n\n* Add `enable_incomplete` option to allow adapter to start without a complete config.\n\n# 1.0.2\n\nThis was the first public release\n"
  },
  {
    "path": "packages/botbuilder-adapter-facebook/LICENSE.md",
    "content": "Copyright XOXCO, Inc, http://xoxco.com, http://howdy.ai\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "packages/botbuilder-adapter-facebook/package.json",
    "content": "{\n  \"name\": \"botbuilder-adapter-facebook\",\n  \"version\": \"1.0.12\",\n  \"description\": \"Connect Botkit or BotBuilder to Facebook Messenger\",\n  \"main\": \"lib/index.js\",\n  \"typings\": \"./lib/index.d.ts\",\n  \"files\": [\n    \"/lib\",\n    \"/src\"\n  ],\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"test\": \"tsc ; nyc mocha tests/*.tests.js\",\n    \"eslint\": \"./node_modules/.bin/eslint --fix src/*\",\n    \"pack\": \"npm pack\"\n  },\n  \"author\": \"Microsoft Corp.\",\n  \"license\": \"MIT\",\n  \"keywords\": [\n    \"facebook\",\n    \"facebook messenger\",\n    \"botkit\",\n    \"botbuilder\",\n    \"botframework\",\n    \"bots\",\n    \"chatbots\",\n    \"azure\"\n  ],\n  \"homepage\": \"https://github.com/howdyai/botkit/blob/master/packages/botbuilder-adapter-facebook#readme\",\n  \"bugs\": {\n    \"url\": \"https://github.com/howdyai/botkit/issues\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/howdyai/botkit.git\"\n  },\n  \"dependencies\": {\n    \"botbuilder\": \"^4.15.0\",\n    \"botkit\": \"^4.15.0\",\n    \"debug\": \"^4.1.0\"\n  },\n  \"devDependencies\": {\n    \"eslint\": \"^8.3.0\",\n    \"eslint-config-standard\": \"^16.0.3\",\n    \"eslint-plugin-import\": \"^2.25.3\",\n    \"eslint-plugin-node\": \"^11.1.0\",\n    \"eslint-plugin-promise\": \"^5.1.1\",\n    \"eslint-plugin-standard\": \"^4.0.1\"\n  }\n}\n"
  },
  {
    "path": "packages/botbuilder-adapter-facebook/readme.md",
    "content": "# botbuilder-adapter-facebook\nConnect [Botkit](https://www.npmjs.com/package/botkit) or [BotBuilder](https://www.npmjs.com/package/botbuilder) to Facebook Messenger.\n\nThis package contains an adapter that communicates directly with the Facebook Messenger API,\nand translates messages to and from a standard format used by your bot. This package can be used alongside your favorite bot development framework to build bots that work with Facebook Messenger.\n\n## Install Package\n\nAdd this package to your project using npm:\n\n```bash\nnpm install --save botbuilder-adapter-facebook\n```\n\nImport the adapter class into your code:\n\n```javascript\nconst { FacebookAdapter } = require('botbuilder-adapter-facebook');\n```\n\n## Get Started\n\nIf you are starting a brand new project, [follow these instructions to create a customized application template.](../docs/index.md)\n\n## Use FacebookAdapter in your App\n\nFacebookAdapter provides a translation layer for Botkit and BotBuilder so that bot developers can connect to Facebook Messenger and have access to Facebook's API.\n\n### Botkit Basics\n\nWhen used in concert with Botkit, developers need only pass the configured adapter to the Botkit constructor, as seen below. Botkit will automatically create and configure the webhook endpoints and other options necessary for communicating with Facebook.\n\nDevelopers can then bind to Botkit's event emitting system using `controller.on` and `controller.hears` to filter and handle incoming events from the messaging platform. [Learn more about Botkit's core feature &rarr;](../docs/index.md).\n\n[A full description of the FacebookAdapter options and example code can be found in the class reference docs.](../docs/reference/facebook.md#create-a-new-facebookadapter)\n\n```javascript\nconst adapter = new FacebookAdapter({\n     verify_token: process.env.FACEBOOK_VERIFY_TOKEN,\n     app_secret: process.env.FACEBOOK_APP_SECRET,\n     access_token: process.env.FACEBOOK_ACCESS_TOKEN\n});\n\nadapter.use(new FacebookEventTypeMiddleware());\n\nconst controller = new Botkit({\n    adapter,\n    // ...other options\n});\n\ncontroller.on('message', async(bot, message) => {\n    await bot.reply(message, 'I heard a message!');\n});\n```\n\n### BotBuilder Basics\n\nAlternately, developers may choose to use `FacebookAdapter` with BotBuilder. With BotBuilder, the adapter is used more directly with a webserver, and all incoming events are handled as [Activities](https://docs.microsoft.com/en-us/javascript/api/botframework-schema/activity?view=botbuilder-ts-latest).\n\n```javascript\nconst { FacebookAdapter } = require('botbuilder-adapter-facebook');\nconst restify = require('restify');\n\nconst adapter = new FacebookAdapter({\n     verify_token: process.env.FACEBOOK_VERIFY_TOKEN,\n     app_secret: process.env.FACEBOOK_APP_SECRET,\n     access_token: process.env.FACEBOOK_ACCESS_TOKEN\n});\nconst server = restify.createServer();\nserver.use(restify.plugins.bodyParser());\nserver.use(restify.plugins.queryParser());\n\nserver.get('/api/messages', (req, res) => {\n     if (req.query['hub.mode'] === 'subscribe') {\n          if (req.query['hub.verify_token'] === process.env.FACEBOOK_VERIFY_TOKEN) {\n               const val = req.query['hub.challenge'];\n               res.sendRaw(200, val);\n          } else {\n               console.log('failed to verify endpoint');\n               res.send('OK');\n          }\n     }\n});\n\nserver.post('/api/messages', (req, res) => {\n     adapter.processActivity(req, res, async(context) => {\n         await context.sendActivity('I heard a message!');\n     });\n});\n\nserver.listen(process.env.port || process.env.PORT || 3000, () => {\n     console.log(`\\n${ server.name } listening to ${ server.url }`);\n });\n```\n\n### Multi-page Support\n\nIn the examples above, the `FacebookAdapter` constructor received a single `access_token` parameters. This binds the adapter and all API calls it makes to a single Facebook page.\n\nTo use `FacebookAdapter` with multiple Facebook pages, the constructor must receive a function as a paramter named `getAccessTokenForPage` that is responsible for returning a token value when provided a Facebook page ID. The application must implement its own mechanism for securely storing and retrieving the token.\n\n```javascript\nconst adapter = new FacebookAdapter({\n    verify_token: process.env.FACEBOOK_VERIFY_TOKEN,\n    app_secret: process.env.FACEBOOK_APP_SECRET,\n    getAccessTokenForPage: async(pageId) => { \n        // do something to fetch the page access token for pageId.\n        return token;\n    }\n});\n```\n\n## Class Reference\n\n* [FacebookAdapter](../docs/reference/facebook.md#facebookadapter)\n* [BotWorker Extensions](../docs/reference/facebook.md#facebookbotworker)\n* [Facebook API Client](../docs/reference/facebook.md#facebookapi)\n\n## Event List\n\n[Botkit event types are controlled by the FacebookEventMiddleware](../docs/reference/facebook.md#facebookeventtypemiddleware).\n\nWithout this middleware applied, Botkit bots will receive `message` events when a user types a message or clicks a postback_button, and an `event` event for all other types of event received from Facebook.\n\nMost Botkit developers who plan to use features above and beyond Facebook's send API should enable this middleware.\n\n## Calling Facebook APIs\n\nThis package also includes [a minimal Facebook API client](../docs/reference/facebook.md#facebookapi) for developers who want to use one of the many available API endpoints.\n\nIn Botkit handlers, the `bot` worker object passed into all handlers will contain a `bot.api` field that contains the client, preconfigured and ready to use.\n\nTo use with a BotBuilder application, the adapter provides the [getAPI() method](../docs/reference/facebook.md#getapi).\n\n```javascript\ncontroller.on('message', async(bot, message) {\n\n    // call the facebook API to get the bot's page identity\n    let identity = await bot.api.callAPI('/me', 'GET', {});\n    await bot.reply(message,`My name is ${ identity.name }`);\n\n});\n```\n\n## Botkit Extensions\n\nIn Botkit handlers, the `bot` worker for Facebook contains [all of the base methods](../docs/reference/core.md#BotWorker) as well as the following platform-specific extensions:\n\n### Use attachments, quick replies and other rich message features\n\nBotkit will automatically construct your outgoing messages according to Facebook's specifications. To use attachments, quick replies or other features, add them to the message object used to create the reply:\n\n```javascript\nawait bot.reply(message, {\n    text: 'Choose a button', \n    quick_replies: [\n        {\n            \"content_type\":\"text\",\n            \"title\":\"Foo\",\n            \"payload\":\"true\"\n        },\n        {\n            \"content_type\":\"text\",\n            \"title\":\"Bar\",\n            \"payload\":\"false\"\n        }\n    ]\n});\n```\n\n### [Spawn a worker for a specific page](../docs/reference/facebook.md#create-a-new-facebookbotworker)\n\nFor a bot that works with multiple pages, it is possible to spawn bot workers bound to a specific page by passing the page ID as the primary parameter to `controller.spawn()`:\n\n```javascript\nlet bot = await controller.spawn(FACEBOOK_PAGE_ID);\n```\n\n### [bot.startConversationWithUser()](../docs/reference/facebook.md#startconversationwithuser)\n\nUse this method to initiate a conversation with a user. After calling this method, any further actions carried out by the bot worker will happen with the specified user.\n\nThis can be used to create or resume conversations with users that are not in direct response to an incoming message, like those sent on a schedule or in response to external events.\n\n## Community & Support\n\nJoin our thriving community of Botkit developers and bot enthusiasts at large.\nOver 10,000 members strong, [our open Slack group](https://community.botkit.ai) is\n_the place_ for people interested in the art and science of making bots.\nCome to ask questions, share your progress, and commune with your peers!\n\nYou can also find help from members of the Botkit team [in our dedicated Cisco Spark room](https://eurl.io/#SyNZuomKx)!\n\n## About Botkit\n\nBotkit is a part of the [Microsoft Bot Framework](https://dev.botframework.com).\n\nWant to contribute? [Read the contributor guide](https://github.com/howdyai/botkit/blob/master/CONTRIBUTING.md)\n\nBotkit is released under the [MIT Open Source license](https://github.com/howdyai/botkit/blob/master/LICENSE.md)\n"
  },
  {
    "path": "packages/botbuilder-adapter-facebook/src/botworker.ts",
    "content": "/**\n * @module botbuilder-adapter-facebook\n */\n/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { Botkit, BotWorker } from 'botkit';\nimport { FacebookAPI } from './facebook_api';\n\n/**\n * This is a specialized version of [Botkit's core BotWorker class](core.md#BotWorker) that includes additional methods for interacting with Facebook.\n * It includes all functionality from the base class, as well as the extension methods below.\n *\n * When using the FacebookAdapter with Botkit, all `bot` objects passed to handler functions will include these extensions.\n */\nexport class FacebookBotWorker extends BotWorker {\n    /**\n     * A copy of the FacebookAPI client giving access to `let res = await bot.api.callAPI(path, method, parameters);`\n     */\n    public api: FacebookAPI;\n\n    /**\n     * Reserved for use internally by Botkit's `controller.spawn()`, this class is used to create a BotWorker instance that can send messages, replies, and make other API calls.\n     *\n     * When used with the FacebookAdapter's multi-tenancy mode, it is possible to spawn a bot instance by passing in the Facebook page ID representing the appropriate bot identity.\n     * Use this in concert with [startConversationWithUser()](#startConversationWithUser) and [changeContext()](core.md#changecontext) to start conversations\n     * or send proactive alerts to users on a schedule or in response to external events.\n     *\n     * ```javascript\n     * let bot = await controller.spawn(FACEBOOK_PAGE_ID);\n     * ```\n     * @param botkit The Botkit controller object responsible for spawning this bot worker.\n     * @param config Normally, a DialogContext object.  Can also be the ID of a Facebook page managed by this app.\n     */\n    public constructor(botkit: Botkit, config: any) {\n        // allow a page id to be passed in\n        if (typeof config === 'string') {\n            const page_id = config;\n            config = {\n                // an activity is required to spawn the bot via the api\n                activity: {\n                    channelId: 'facebook',\n                    recipient: {\n                        id: page_id\n                    }\n                }\n            };\n        }\n\n        super(botkit, config);\n    }\n\n    // TODO: Typing indicators\n\n    /**\n     * Change the operating context of the worker to begin a conversation with a specific user.\n     * After calling this method, any calls to `bot.say()` or `bot.beginDialog()` will occur in this new context.\n     *\n     * This method can be used to send users scheduled messages or messages triggered by external events.\n     * ```javascript\n     * let bot = await controller.spawn(FACEBOOK_PAGE_ID);\n     * await bot.startConversationWithUser(FACEBOOK_USER_PSID);\n     * await bot.say('Howdy human!');\n     * ```\n     *\n     * @param userId the PSID of a user the bot has previously interacted with\n     */\n    public async startConversationWithUser(userId): Promise<void> {\n        await this.changeContext({\n            channelId: 'facebook',\n            // @ts-ignore\n            conversation: { id: userId },\n            bot: this.getConfig('activity').recipient,\n            // @ts-ignore\n            user: { id: userId }\n        });\n    }\n}\n"
  },
  {
    "path": "packages/botbuilder-adapter-facebook/src/facebook_adapter.ts",
    "content": "/**\n * @module botbuilder-adapter-facebook\n */\n/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { Activity, ActivityTypes, BotAdapter, TurnContext, ConversationReference, ResourceResponse } from 'botbuilder';\nimport * as Debug from 'debug';\nimport { FacebookBotWorker } from './botworker';\nimport { FacebookAPI } from './facebook_api';\nimport * as crypto from 'crypto';\nconst debug = Debug('botkit:facebook');\n\n/**\n * Connect [Botkit](https://www.npmjs.com/package/botkit) or [BotBuilder](https://www.npmjs.com/package/botbuilder) to Facebook Messenger.\n */\nexport class FacebookAdapter extends BotAdapter {\n    /**\n     * Name used by Botkit plugin loader\n     * @ignore\n     */\n    public name = 'Facebook Adapter';\n\n    /**\n     * Object containing one or more Botkit middlewares to bind automatically.\n     * @ignore\n     */\n    public middlewares;\n\n    /**\n     * A customized BotWorker object that exposes additional utility methods.\n     * @ignore\n     */\n    public botkit_worker = FacebookBotWorker;\n\n    private options: FacebookAdapterOptions;\n\n    /**\n     * Create an adapter to handle incoming messages from Facebook and translate them into a standard format for processing by your bot.\n     *\n     * The Facebook Adapter can be used in 2 modes:\n     * * bound to a single Facebook page\n     * * multi-tenancy mode able to serve multiple pages\n     *\n     * To create an app bound to a single Facebook page, include that page's `access_token` in the options.\n     *\n     * To create an app that can be bound to multiple pages, include `getAccessTokenForPage` - a function in the form `async (pageId) => page_access_token`\n     *\n     * To use with Botkit:\n     * ```javascript\n     * const adapter = new FacebookAdapter({\n     *      verify_token: process.env.FACEBOOK_VERIFY_TOKEN,\n     *      app_secret: process.env.FACEBOOK_APP_SECRET,\n     *      access_token: process.env.FACEBOOK_ACCESS_TOKEN\n     * });\n     * const controller = new Botkit({\n     *      adapter: adapter,\n     *      // other options\n     * });\n     * ```\n     *\n     * To use with BotBuilder:\n     * ```javascript\n     * const adapter = new FacebookAdapter({\n     *      verify_token: process.env.FACEBOOK_VERIFY_TOKEN,\n     *      app_secret: process.env.FACEBOOK_APP_SECRET,\n     *      access_token: process.env.FACEBOOK_ACCESS_TOKEN\n     * });\n     * const server = restify.createServer();\n     * server.use(restify.plugins.bodyParser());\n     * server.post('/api/messages', (req, res) => {\n     *      adapter.processActivity(req, res, async(context) => {\n     *          // do your bot logic here!\n     *      });\n     * });\n     * ```\n     *\n     * In multi-tenancy mode:\n     * ```javascript\n     * const adapter = new FacebookAdapter({\n     *      verify_token: process.env.FACEBOOK_VERIFY_TOKEN,\n     *      app_secret: process.env.FACEBOOK_APP_SECRET,\n     *       getAccessTokenForPage: async(pageId) => {\n     *           // do something to fetch the page access token for pageId.\n     *           return token;\n     *       })\n     * });\n     *```\n     *\n     * @param options Configuration options\n     */\n    public constructor(options: FacebookAdapterOptions) {\n        super();\n\n        this.options = {\n            api_host: 'graph.facebook.com',\n            api_version: 'v3.2',\n            ...options\n        };\n\n        if (!this.options.access_token && !this.options.getAccessTokenForPage) {\n            const err = 'Adapter must receive either an access_token or a getAccessTokenForPage function.';\n            if (!this.options.enable_incomplete) {\n                throw new Error(err);\n            } else {\n                console.error(err);\n            }\n        }\n\n        if (!this.options.app_secret) {\n            const err = 'Provide an app_secret in order to validate incoming webhooks and better secure api requests';\n            if (!this.options.enable_incomplete) {\n                throw new Error(err);\n            } else {\n                console.error(err);\n            }\n        }\n\n        if (this.options.enable_incomplete) {\n            const warning = [\n                '',\n                '****************************************************************************************',\n                '* WARNING: Your adapter may be running with an incomplete/unsafe configuration.        *',\n                '* - Ensure all required configuration options are present                              *',\n                '* - Disable the \"enable_incomplete\" option!                                            *',\n                '****************************************************************************************',\n                ''\n            ];\n            console.warn(warning.join('\\n'));\n        }\n\n        this.middlewares = {\n            spawn: [\n                async (bot, next): Promise<void> => {\n                    bot.api = await this.getAPI(bot.getConfig('activity'));\n                    next();\n                }\n            ]\n        };\n    }\n\n    /**\n     * Botkit-only: Initialization function called automatically when used with Botkit.\n     *      * Amends the webhook_uri with an additional behavior for responding to Facebook's webhook verification request.\n     * @param botkit\n     */\n    public async init(botkit): Promise<any> {\n        debug('Add GET webhook endpoint for verification at: ', botkit.getConfig('webhook_uri'));\n        if (botkit.webserver) {\n            botkit.webserver.get(botkit.getConfig('webhook_uri'), (req, res) => {\n                if (req.query['hub.mode'] === 'subscribe') {\n                    if (req.query['hub.verify_token'] === this.options.verify_token) {\n                        res.send(req.query['hub.challenge']);\n                    } else {\n                        res.send('OK');\n                    }\n                }\n            });\n        }\n    }\n\n    /**\n     * Get a Facebook API client with the correct credentials based on the page identified in the incoming activity.\n     * This is used by many internal functions to get access to the Facebook API, and is exposed as `bot.api` on any BotWorker instances passed into Botkit handler functions.\n     *\n     * ```javascript\n     * let api = adapter.getAPI(activity);\n     * let res = api.callAPI('/me/messages', 'POST', message);\n     * ```\n     * @param activity An incoming message activity\n     */\n    public async getAPI(activity: Partial<Activity>): Promise<FacebookAPI> {\n        if (this.options.access_token) {\n            return new FacebookAPI(this.options.access_token, this.options.app_secret, this.options.api_host, this.options.api_version);\n        } else {\n            if (activity.recipient.id) {\n                let pageid = activity.recipient.id;\n                // if this is an echo, the page id is actually in the from field\n                if (activity.channelData && activity.channelData.message && activity.channelData.message.is_echo === true) {\n                    pageid = activity.from.id;\n                }\n                const token = await this.options.getAccessTokenForPage(pageid);\n                if (!token) {\n                    throw new Error('Missing credentials for page.');\n                }\n                return new FacebookAPI(token, this.options.app_secret, this.options.api_host, this.options.api_version);\n            } else {\n                // No API can be created, this is\n                debug('Unable to create API based on activity: ', activity);\n            }\n        }\n    }\n\n    /**\n     * Converts an Activity object to a Facebook messenger outbound message ready for the API.\n     * @param activity\n     */\n    private activityToFacebook(activity: any): any {\n        const message = {\n            recipient: {\n                id: activity.conversation.id\n            },\n            message: {\n                text: activity.text,\n                sticker_id: undefined,\n                attachment: undefined,\n                quick_replies: undefined\n            },\n            messaging_type: 'RESPONSE',\n            tag: undefined,\n            notification_type: undefined,\n            persona_id: undefined,\n            sender_action: undefined\n        };\n\n        // map these fields to their appropriate place\n        if (activity.channelData) {\n            if (activity.channelData.messaging_type) {\n                message.messaging_type = activity.channelData.messaging_type;\n            }\n\n            if (activity.channelData.tag) {\n                message.tag = activity.channelData.tag;\n            }\n\n            if (activity.channelData.sticker_id) {\n                message.message.sticker_id = activity.channelData.sticker_id;\n            }\n\n            if (activity.channelData.attachment) {\n                message.message.attachment = activity.channelData.attachment;\n            }\n\n            if (activity.channelData.persona_id) {\n                message.persona_id = activity.channelData.persona_id;\n            }\n\n            if (activity.channelData.notification_type) {\n                message.notification_type = activity.channelData.notification_type;\n            }\n\n            if (activity.channelData.sender_action) {\n                message.sender_action = activity.channelData.sender_action;\n\n                // from docs: https://developers.facebook.com/docs/messenger-platform/reference/send-api/\n                // Cannot be sent with message. Must be sent as a separate request.\n                // When using sender_action, recipient should be the only other property set in the request.\n                delete (message.message);\n            }\n\n            // make sure the quick reply has a type\n            if (activity.channelData.quick_replies) {\n                message.message.quick_replies = activity.channelData.quick_replies.map(function(item) {\n                    const quick_reply = { ...item };\n                    if (!item.content_type) quick_reply.content_type = 'text';\n                    return quick_reply;\n                });\n            }\n        }\n\n        debug('OUT TO FACEBOOK > ', message);\n\n        return message;\n    }\n\n    /**\n     * Standard BotBuilder adapter method to send a message from the bot to the messaging API.\n     * [BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#sendactivities).\n     * @param context A TurnContext representing the current incoming message and environment.\n     * @param activities An array of outgoing activities to be sent back to the messaging API.\n     */\n    public async sendActivities(context: TurnContext, activities: Partial<Activity>[]): Promise<ResourceResponse[]> {\n        const responses = [];\n        for (let a = 0; a < activities.length; a++) {\n            const activity = activities[a];\n            if (activity.type === ActivityTypes.Message) {\n                const message = this.activityToFacebook(activity);\n                try {\n                    const api = await this.getAPI(context.activity);\n                    const res = await api.callAPI('/me/messages', 'POST', message);\n                    if (res) {\n                        responses.push({ id: res.message_id });\n                    }\n                    debug('RESPONSE FROM FACEBOOK > ', res);\n                } catch (err) {\n                    console.error('Error sending activity to Facebook:', err);\n                }\n            } else {\n                // If there are ever any non-message type events that need to be sent, do it here.\n                debug('Unknown message type encountered in sendActivities: ', activity.type);\n            }\n        }\n\n        return responses;\n    }\n\n    /**\n     * Facebook adapter does not support updateActivity.\n     * @ignore\n     */\n    // eslint-disable-next-line\n    public async updateActivity(context: TurnContext, activity: Partial<Activity>): Promise<void> {\n        debug('Facebook adapter does not support updateActivity.');\n    }\n\n    /**\n     * Facebook adapter does not support updateActivity.\n     * @ignore\n     */\n    // eslint-disable-next-line\n     public async deleteActivity(context: TurnContext, reference: Partial<ConversationReference>): Promise<void> {\n        debug('Facebook adapter does not support deleteActivity.');\n    }\n\n    /**\n     * Standard BotBuilder adapter method for continuing an existing conversation based on a conversation reference.\n     * [BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#continueconversation)\n     * @param reference A conversation reference to be applied to future messages.\n     * @param logic A bot logic function that will perform continuing action in the form `async(context) => { ... }`\n     */\n    public async continueConversation(reference: Partial<ConversationReference>, logic: (context: TurnContext) => Promise<void>): Promise<void> {\n        const request = TurnContext.applyConversationReference(\n            { type: 'event', name: 'continueConversation' },\n            reference,\n            true\n        );\n        const context = new TurnContext(this, request);\n\n        return this.runMiddleware(context, logic);\n    }\n\n    /**\n     * Accept an incoming webhook request and convert it into a TurnContext which can be processed by the bot's logic.\n     * @param req A request object from Restify or Express\n     * @param res A response object from Restify or Express\n     * @param logic A bot logic function in the form `async(context) => { ... }`\n     */\n    public async processActivity(req, res, logic: (context: TurnContext) => Promise<void>): Promise<void> {\n        debug('IN FROM FACEBOOK >', req.body);\n        if (await this.verifySignature(req, res) === true) {\n            const event = req.body;\n            if (event.entry) {\n                for (let e = 0; e < event.entry.length; e++) {\n                    let payload = null;\n                    const entry = event.entry[e];\n\n                    // handle normal incoming stuff\n                    if (entry.changes) {\n                        payload = entry.changes;\n                    } else if (entry.messaging) {\n                        payload = entry.messaging;\n                    }\n\n                    for (let m = 0; m < payload.length; m++) {\n                        await this.processSingleMessage(payload[m], logic);\n                    }\n\n                    // handle standby messages (this bot is not the active receiver)\n                    if (entry.standby) {\n                        payload = entry.standby;\n\n                        for (let m = 0; m < payload.length; m++) {\n                            const message = payload[m];\n                            // indiciate that this message was received in standby mode rather than normal mode.\n                            message.standby = true;\n                            await this.processSingleMessage(message, logic);\n                        }\n                    }\n                }\n\n                res.status(200);\n                res.end();\n            }\n        }\n    }\n\n    /**\n     * Handles each individual message inside a webhook payload (webhook may deliver more than one message at a time)\n     * @param message\n     * @param logic\n     */\n    private async processSingleMessage(message: any, logic: any): Promise<void> {\n        //  in case of Checkbox Plug-in sender.id is not present, instead we should look at optin.user_ref\n        if (!message.sender && message.optin && message.optin.user_ref) {\n            message.sender = { id: message.optin.user_ref };\n        }\n\n        const activity: Activity = {\n            channelId: 'facebook',\n            timestamp: new Date(),\n            // @ts-ignore ignore missing optional fields\n            conversation: {\n                id: message.sender.id\n            },\n            from: {\n                id: message.sender.id,\n                name: message.sender.id\n            },\n            recipient: {\n                id: message.recipient.id,\n                name: message.recipient.id\n            },\n            channelData: message,\n            type: ActivityTypes.Event,\n            text: null\n        };\n\n        if (message.message) {\n            activity.type = ActivityTypes.Message;\n            activity.text = message.message.text;\n\n            if (activity.channelData.message.is_echo) {\n                activity.type = ActivityTypes.Event;\n            }\n\n            // copy fields like attachments, sticker, quick_reply, nlp, etc.\n            for (const key in message.message) {\n                activity.channelData[key] = message.message[key];\n            }\n        } else if (message.postback) {\n            activity.type = ActivityTypes.Message;\n            activity.text = message.postback.payload;\n        }\n\n        const context = new TurnContext(this, activity as Activity);\n        await this.runMiddleware(context, logic);\n    }\n\n    /*\n     * Verifies the SHA1 signature of the raw request payload before bodyParser parses it\n     * Will abort parsing if signature is invalid, and pass a generic error to response\n     */\n    private async verifySignature(req, res): Promise<boolean> {\n        const expected = req.headers['x-hub-signature'];\n        const hmac = crypto.createHmac('sha1', this.options.app_secret);\n        hmac.update(req.rawBody, 'utf8');\n        const calculated = 'sha1=' + hmac.digest('hex');\n        if (expected !== calculated) {\n            res.status(401);\n            debug('Token verification failed, Ignoring message');\n            throw new Error('Invalid signature on incoming request');\n        } else {\n            return true;\n        }\n    }\n}\n\n/**\n * This interface defines the options that can be passed into the FacebookAdapter constructor function.\n */\nexport interface FacebookAdapterOptions {\n    /**\n     * Alternate root url used to contruct calls to Facebook's API.  Defaults to 'graph.facebook.com' but can be changed (for mocking, proxy, etc).\n     */\n    api_host?: string;\n    /**\n     * Alternate API version used to construct calls to Facebook's API. Defaults to v3.2\n     */\n    api_version?: string;\n\n    /**\n     * The \"verify token\" used to initially create and verify the Webhooks subscription settings on Facebook's developer portal.\n     */\n    verify_token: string;\n\n    /**\n     * The \"app secret\" from the \"basic settings\" page from your app's configuration in the Facebook developer portal\n     */\n    app_secret: string;\n\n    /**\n     * When bound to a single page, use `access_token` to specify the \"page access token\" provided in the Facebook developer portal's \"Access Tokens\" widget of the \"Messenger Settings\" page.\n     */\n    access_token?: string;\n\n    /**\n     * When bound to multiple teams, provide a function that, given a page id, will return the page access token for that page.\n     */\n    getAccessTokenForPage?: (pageId: string) => Promise<string>;\n\n    /**\n     * Allow the adapter to startup without a complete configuration.\n     * This is risky as it may result in a non-functioning or insecure adapter.\n     * This should only be used when getting started.\n     */\n    enable_incomplete?: boolean;\n}\n"
  },
  {
    "path": "packages/botbuilder-adapter-facebook/src/facebook_api.ts",
    "content": "/**\n * @module botbuilder-adapter-facebook\n */\n/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport * as request from 'request';\nimport * as crypto from 'crypto';\n\n/**\n * A simple API client for the Facebook API.  Automatically signs requests with the access token and app secret proof.\n * It can be used to call any API provided by Facebook.\n *\n */\nexport class FacebookAPI {\n    private token: string;\n    private secret: string;\n    private api_host: string;\n    private api_version: string;\n\n    /**\n     * Create a FacebookAPI client.\n     * ```\n     * let api = new FacebookAPI(TOKEN, SECRET);\n     * await api.callAPI('/some/api','POST', {some_options});\n     * ```\n     * @param token a page access token\n     * @param secret an app secret\n     * @param api_host optional root hostname for constructing api calls, defaults to graph.facebook.com\n     * @param api_version optional api version used when constructing api calls, defaults to v3.2\n     */\n    public constructor(token: string, secret: string, api_host = 'graph.facebook.com', api_version = 'v3.2') {\n        if (!token) {\n            throw new Error('Token is required!');\n        }\n        this.token = token;\n        this.secret = secret;\n        this.api_host = api_host;\n        this.api_version = api_version;\n    }\n\n    /**\n     * Call one of the Facebook APIs\n     * @param path Path to the API endpoint, for example `/me/messages`\n     * @param method HTTP method, for example POST, GET, DELETE or PUT.\n     * @param payload An object to be sent as parameters to the API call.\n     */\n    public async callAPI(path: string, method = 'POST', payload: any = {}): Promise<any> {\n        const proof = this.getAppSecretProof(this.token, this.secret);\n\n        let queryString = '?';\n        let body = {};\n\n        if (method.toUpperCase() === 'GET') {\n            for (const key in payload) {\n                queryString = queryString + `${ encodeURIComponent(key) }=${ encodeURIComponent(payload[key]) }&`;\n            }\n        } else {\n            body = payload;\n        }\n\n        return new Promise((resolve, reject) => {\n            request({\n                method: method.toUpperCase(),\n                json: true,\n                body,\n                uri: `https://${ this.api_host }/${ this.api_version }${ path }${ queryString }access_token=${ this.token }&appsecret_proof=${ proof }`\n            }, (err, res, body) => {\n                if (err) {\n                    reject(err);\n                } else if (body.error) {\n                    reject(body.error.message);\n                } else {\n                    resolve(body);\n                }\n            });\n        });\n    }\n\n    /**\n     * Generate the app secret proof used to increase security on calls to the graph API\n     * @param access_token a page access token\n     * @param app_secret an app secret\n     */\n    private getAppSecretProof(access_token, app_secret): string {\n        const hmac = crypto.createHmac('sha256', app_secret || '');\n        return hmac.update(access_token).digest('hex');\n    }\n}\n"
  },
  {
    "path": "packages/botbuilder-adapter-facebook/src/facebook_event_middleware.ts",
    "content": "/**\n * @module botbuilder-adapter-facebook\n */\n/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { MiddlewareSet, ActivityTypes } from 'botbuilder';\n\n/**\n * This adapter middleware, when used in conjunction with FacebookAdapter and Botkit, will result in Botkit emitting events with\n * names based on their event type.\n *\n * ```javascript\n * const adapter = new FacebookAdapter(MY_OPTIONS);\n * adapter.use(new FacebookEventTypeMiddleware());\n * const controller = new Botkit({\n *      adapter: adapter,\n * });\n *\n * // define a handler for one of the new events\n * controller.on('facebook_option', async(bot, message) => {\n *      // ...\n * });\n * ```\n *\n * When used, events emitted may include:\n * * facebook_postback\n * * facebook_referral\n * * facebook_optin\n * * message_delivered\n * * message_read\n * * facebook_account_linking\n * * message_echo\n * * facebook_app_roles\n * * standby\n * * facebook_receive_thread_control\n * * facebook_request_thread_control\n *\n */\nexport class FacebookEventTypeMiddleware extends MiddlewareSet {\n    /**\n     * Implements the middleware's onTurn function. Called automatically.\n     * @ignore\n     * @param context\n     * @param next\n     */\n    public async onTurn(context, next): Promise<void> {\n        if (context.activity && context.activity.channelData) {\n            let type = null;\n            if (context.activity.channelData.postback) {\n                type = 'facebook_postback';\n            } else if (context.activity.channelData.referral) {\n                type = 'facebook_referral';\n            } else if (context.activity.channelData.optin) {\n                type = 'facebook_optin';\n            } else if (context.activity.channelData.delivery) {\n                type = 'message_delivered';\n            } else if (context.activity.channelData.read) {\n                type = 'message_read';\n            } else if (context.activity.channelData.account_linking) {\n                type = 'facebook_account_linking';\n            } else if (context.activity.channelData.message && context.activity.channelData.message.is_echo) {\n                type = 'message_echo';\n                context.activity.type = ActivityTypes.Event;\n            } else if (context.activity.channelData.app_roles) {\n                type = 'facebook_app_roles';\n            } else if (context.activity.channelData.standby) {\n                type = 'standby';\n            } else if (context.activity.channelData.pass_thread_control) {\n                type = 'facebook_receive_thread_control';\n            } else if (context.activity.channelData.take_thread_control) {\n                type = 'facebook_lose_thread_control';\n            } else if (context.activity.channelData.request_thread_control) {\n                type = 'facebook_request_thread_control';\n            }\n\n            context.activity.channelData.botkitEventType = type;\n        }\n\n        await next();\n    }\n}\n"
  },
  {
    "path": "packages/botbuilder-adapter-facebook/src/index.ts",
    "content": "/**\n * @module botbuilder-adapter-facebook\n */\n/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport * from './botworker';\nexport * from './facebook_adapter';\nexport * from './facebook_api';\nexport * from './facebook_event_middleware';\n"
  },
  {
    "path": "packages/botbuilder-adapter-facebook/tests/FacebookAdapter.tests.js",
    "content": "const assert = require('assert');\nconst { FacebookAdapter } = require('../');\nconst { FakeAPI, Res, Req, fakeVerifySignature } = require('./shared');\n\ndescribe('FacebookAdapter', function() {\n\n    let adapter;\n\n    beforeEach(function () {\n        adapter = new FacebookAdapter({\n            getAccessTokenForPage: async (page) => {\n                if (page === 2) { return 'xyz'; } else throw new Error('no token for ' + page);\n            },\n            app_secret: '123',\n            verify_token: '123',\n        });\n    })\n\n    it('should not construct without required parameters', function () {\n        assert.throws(function () { let adapter = new FacebookAdapter({}) }, 'Foo');\n    });\n\n    it('should create a FacebookAdapter object', function () {\n        assert((adapter instanceof FacebookAdapter), 'Adapter is wrong type');\n    });\n\n    it('should process an incoming request into an activity...', function (done) {\n        adapter.verifySignature = fakeVerifySignature;\n        let res = new Res();\n        adapter.processActivity(new Req({\n            entry: [\n                {\n                    messaging: [\n                        {\n                            sender: { id: 1 },\n                            recipient: { id: 2 },\n                            message: {\n                                text: 'Hello!',\n                                sticker_id: 1,\n                            }\n                        }\n                    ]\n                }\n            ]\n        }), res, async (context) => {\n            assert(context.activity.type === 'message', 'activity is not a message');\n            assert(context.activity.text === 'Hello!', 'activity is missing text');\n            assert(context.activity.from.id === 1,'from id is wrong');\n            assert(context.activity.recipient.id === 2,'from id is wrong');\n            assert(context.activity.channelData.sticker_id === 1, 'platform field is not in channelData');\n            done();\n        });\n    });\n\n\n\n    it ('should process an postback incoming request into an activity...', function(done) {\n        adapter.verifySignature = fakeVerifySignature;\n        let res = new Res();\n        adapter.processActivity(new Req({\n            entry: [\n                {\n                    messaging: [\n                        {\n                            sender: { id: 1 },\n                            recipient: { id: 2 },\n                            postback: {\n                                payload: 'Hello!'\n                            }\n                        }\n                    ]\n                }\n            ]\n        }), res, async(context) => {\n            assert(context.activity.type === 'message', 'activity is not a message');\n            assert(context.activity.text === 'Hello!', 'activity is missing text');\n            done();\n        });\n    });\n\n    it ('should process a message echo incoming request into an event...', function(done) {\n        adapter.verifySignature = fakeVerifySignature;\n        let res = new Res();\n        adapter.processActivity(new Req({\n            entry: [\n                {\n                    messaging: [\n                        {\n                            sender: { id: 1 },\n                            recipient: { id: 2 },\n                            message: {\n                                is_echo: true,\n                                text: 'Hello!'\n                            }\n                        }\n                    ]\n                }\n            ]\n        }), res, async(context) => {\n            assert(context.activity.type === 'event', 'activity is not a event');\n            done();\n        });\n    });\n\n\n    it ('should process a non-message incoming request into an event...', function(done) {\n        adapter.verifySignature = fakeVerifySignature;\n        let res = new Res();\n        adapter.processActivity(new Req({\n            entry: [\n                {\n                    messaging: [\n                        {\n                            sender: { id: 1 },\n                            recipient: { id: 2 },\n                            read: {\n                                mid: 1,\n                            }\n                        }\n                    ]\n                }\n            ]\n        }), res, async(context) => {\n            assert(context.activity.type === 'event', 'activity is not a event');\n            done();\n        });\n    });\n\n    it ('should process spawn using the right token.', function(done) {\n        adapter.verifySignature = fakeVerifySignature;\n        let res = new Res();\n        adapter.processActivity(new Req({\n            entry: [\n                {\n                    messaging: [\n                        {\n                            sender: { id: 1 },\n                            recipient: { id: 2 },\n                            message: {\n                                text: 'hi',\n                            }\n                        }\n                    ]\n                }\n            ]\n        }), res, async(context) => {\n            let api = await adapter.getAPI(context.activity);\n            assert(api, 'api was returned based on activity');\n            done();\n        });\n    });\n\n    it ('outbound message to facebook is properly formed.', function(done) {\n        adapter.verifySignature = fakeVerifySignature;\n        adapter.getAPI = async (token) => {\n            return new FakeAPI(function(endpoint, method, params) {\n                assert(params.recipient.id === 1,'outbound message has wrong recipient');\n                assert(params.message.text === 'hello','outbound message has wrong text');\n                assert(params.message.sticker_id,'sticker id is missing');\n                assert(params.message.quick_replies.length === 3,'quick replies are missing');\n                done();\n            });\n        };\n        let res = new Res();\n        adapter.processActivity(new Req({\n            entry: [\n                {\n                    messaging: [\n                        {\n                            sender: { id: 1 },\n                            recipient: { id: 2 },\n                            message: {\n                                text: 'hi',\n                            }\n                        }\n                    ]\n                }\n            ]\n        }), res, async(context) => {\n            let reply = await context.sendActivity({\n                text: 'hello',\n                channelData: {\n                    sticker_id: 5,\n                    quick_replies: [\n                        {\n                            title: 'foo',\n                            payload: 'foo',\n                        },\n                        {\n                            title: 'bar',\n                            payload: 'bar',\n                        },\n                        {\n                            title: 'baz',\n                            payload: 'baz',\n                        },\n                    ]\n                }\n            });\n        });\n    });\n      \n    // TODO: test continueConversation resulting in properly formatted messages\n\n});\n"
  },
  {
    "path": "packages/botbuilder-adapter-facebook/tests/FacebookEventMiddleware.tests.js",
    "content": "const assert = require('assert');\nconst { FacebookAdapter, FacebookEventTypeMiddleware } = require('../');\nconst { Res, Req, fakeVerifySignature } = require('./shared');\n\ndescribe('FacebookEventTypeMiddleware', function() {\n\n    it ('should process a non-message incoming request into an event...', function(done) {\n\n        const adapter = new FacebookAdapter({\n            access_token: '123',\n            app_secret: '123',\n            verify_token: '123',\n        });\n\n        adapter.use(new FacebookEventTypeMiddleware());\n\n        adapter.verifySignature = fakeVerifySignature;\n        let res = new Res();\n        adapter.processActivity(new Req({\n            entry: [\n                {\n                    messaging: [\n                        {\n                            sender: { id: 1 },\n                            recipient: { id: 2 },\n                            read: {\n                                mid: 1,\n                            }\n                        }\n                    ]\n                }\n            ]\n        }), res, async(context) => {\n            assert(context.activity.type === 'event', 'activity is not a event');\n            assert(context.activity.channelData.botkitEventType === 'message_read', 'botkitEventType not set properly');\n\n            done();\n        });\n    });\n});\n"
  },
  {
    "path": "packages/botbuilder-adapter-facebook/tests/shared.js",
    "content": "\nmodule.exports.FakeAPI = class FakeAPI {\n    constructor(cb) {\n        this.cb = cb;\n    }\n    callAPI(endpoint, method, params) {\n        this.cb(endpoint, method, params);\n    }\n}\nmodule.exports.Req = class Req {\n    constructor(body) {\n        this.body = body;\n    }\n}\n\nmodule.exports.Res = class Res {\n    send(val) { \n        this._sent = val;\n        // console.log('SEND', val);\n        return this;\n    }\n    status(status) {\n        this._status = status;\n        // console.log('STATUS', status);\n        return this;\n    }\n    json(json) {\n        this._json = json;\n        // console.log('JSON', json);\n        return this;\n    }\n    end(val) {\n        // console.log('END', val);\n        return this;\n    }\n}\n\nmodule.exports.fakeVerifySignature = fakeVerifySignature = async (req, res) => {\n    return true;\n}"
  },
  {
    "path": "packages/botbuilder-adapter-facebook/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2015\",\n    \"module\": \"commonjs\",\n    \"declaration\": true,\n    \"sourceMap\": true,\n    \"outDir\": \"./lib\",\n    \"rootDir\": \"./src\",\n    \"types\" : [\"node\"],\n    \"lib\": [\n      \"es5\",\n      \"es2015\",\n      \"es2016.array.include\",\n      \"esnext.asynciterable\",\n      \"dom\"\n    ]\n  },\n  \"include\": [\n    \"src/**/*\"\n  ]\n}"
  },
  {
    "path": "packages/botbuilder-adapter-hangouts/.eslintrc.js",
    "content": "module.exports = {\n    \"extends\": \"standard\",\n    \"rules\": {\n        \"semi\": [2, \"always\"],\n        \"indent\": [2, 4],\n        \"no-return-await\": 0,\n        \"camelcase\": 0,\n        \"no-unused-vars\": 0,\n        \"@typescript-eslint/indent\": 0,\n        \"@typescript-eslint/ban-ts-ignore\": 1,\n        \"@typescript-eslint/no-object-literal-type-assertion\": 0,\n        \"@typescript-eslint/explicit-member-accessibility\": 1,\n        \"space-before-function-paren\": [2, {\n            \"named\": \"never\",\n            \"anonymous\": \"never\",\n            \"asyncArrow\": \"always\"\n        }],\n        \"template-curly-spacing\": [2, \"always\"]\n    }\n};"
  },
  {
    "path": "packages/botbuilder-adapter-hangouts/.gitignore",
    "content": "node_modules/\n.env\nlib/\n.nyc_output/\n"
  },
  {
    "path": "packages/botbuilder-adapter-hangouts/CHANGELOG.md",
    "content": "# botbuilder-adapter-hangouts changelog\n\n\n# 1.0.8\n\n* Update dependencies to Botkit 4.10, Bot Framework 4.10\n\n# 1.0.7\n\n* Update dependencies to Botkit 4.9, Bot Framework 4.9\n\n# 1.0.4\n\n* Update dependencies (Bot Framework to 4.6, Botkit to 4.6)\n\n# 1.0.3\n\n* Update dependencies (Bot Framework to 4.5.2, Botkit to 4.5)\n\n# 1.0.2\n\n* Add `enable_incomplete` option to allow adapter to start without a complete config.\n\n# 1.0.1 \n\nFirst public release"
  },
  {
    "path": "packages/botbuilder-adapter-hangouts/LICENSE.md",
    "content": "Copyright XOXCO, Inc, http://xoxco.com, http://howdy.ai\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "packages/botbuilder-adapter-hangouts/package.json",
    "content": "{\n  \"name\": \"botbuilder-adapter-hangouts\",\n  \"version\": \"1.0.9\",\n  \"description\": \"Connect Botkit or BotBuilder to Google Hangouts\",\n  \"main\": \"./lib/index.js\",\n  \"typings\": \"./lib/index.d.ts\",\n  \"files\": [\n    \"/lib\",\n    \"/src\"\n  ],\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"test\": \"tsc ; nyc mocha tests/*.tests.js\",\n    \"eslint\": \"./node_modules/.bin/eslint --fix src/*\",\n    \"pack\": \"npm pack\"\n  },\n  \"author\": \"Microsoft Corp.\",\n  \"license\": \"MIT\",\n  \"keywords\": [\n    \"google hangouts\",\n    \"hangouts\",\n    \"botkit\",\n    \"botbuilder\",\n    \"botframework\",\n    \"bots\",\n    \"chatbots\",\n    \"azure\"\n  ],\n  \"homepage\": \"https://github.com/howdyai/botkit/blob/master/packages/botbuilder-adapter-hangouts#readme\",\n  \"bugs\": {\n    \"url\": \"https://github.com/howdyai/botkit/issues\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/howdyai/botkit.git\"\n  },\n  \"dependencies\": {\n    \"botbuilder\": \"^4.15.0\",\n    \"googleapis\": \"^92.0.0\",\n    \"botkit\": \"^4.15.0\",\n    \"debug\": \"^4.1.0\"\n  },\n  \"devDependencies\": {\n    \"eslint\": \"^8.3.0\",\n    \"eslint-config-standard\": \"^16.0.3\",\n    \"eslint-plugin-import\": \"^2.25.3\",\n    \"eslint-plugin-node\": \"^11.1.0\",\n    \"eslint-plugin-promise\": \"^5.1.1\",\n    \"eslint-plugin-standard\": \"^4.0.1\"\n  }\n}\n"
  },
  {
    "path": "packages/botbuilder-adapter-hangouts/readme.md",
    "content": "# botbuilder-adapter-hangouts\n\nConnect [Botkit](https://www.npmjs.com/package/botkit) or [BotBuilder](https://www.npmjs.com/package/botbuilder) to Google Hangouts.\n\nThis package contains an adapter that communicates directly with the Google Hangouts API,\nand translates messages to and from a standard format used by your bot. This package can be used alongside your favorite bot development framework to build bots that work with Google Hangouts.\n\n## Install Package\n\nAdd this package to your project using npm:\n\n```bash\nnpm install --save botbuilder-adapter-hangouts\n```\n\nImport the adapter class into your code:\n\n```javascript\nconst { HangoutsAdapter } = require('botbuilder-adapter-hangouts');\n```\n\n## Get Started\n\nIf you are starting a brand new project, [follow these instructions to create a customized application template.](../docs/index.md)\n\n## Use HangoutsAdapter in your App\n\nHangoutsAdapter provides a translation layer for Botkit and BotBuilder so that bot developers can connect to Google Hangouts and have access to the Google Hangouts's API.\n\n### Botkit Basics\n\nWhen used in concert with Botkit, developers need only pass the configured adapter to the Botkit constructor, as seen below. Botkit will automatically create and configure the webhook endpoints and other options necessary for communicating with Google.\n\nDevelopers can then bind to Botkit's event emitting system using `controller.on` and `controller.hears` to filter and handle incoming events from the messaging platform. [Learn more about Botkit's core feature &rarr;](../docs/index.md).\n\n[A full description of the HangoutsAdapter options and example code can be found in the class reference docs.](../docs/reference/hangouts.md#create-a-new-hangoutsadapter)\n\n```javascript\nconst adapter = new HangoutsAdapter({\n    token: process.env.GOOGLE_TOKEN,\n    google_auth_params: {\n        credentials: process.env.GOOGLE_CREDS\n    }\n});\n\nconst controller = new Botkit({\n    adapter,\n    // ...other options\n});\n\ncontroller.on('message', async(bot, message) => {\n    await bot.reply(message, 'I heard a message!');\n});\n```\n\n### BotBuilder Basics\n\nAlternately, developers may choose to use `HangoutsAdapter` with BotBuilder. With BotBuilder, the adapter is used more directly with a webserver, and all incoming events are handled as [Activities](https://docs.microsoft.com/en-us/javascript/api/botframework-schema/activity?view=botbuilder-ts-latest).\n\n```javascript\nconst adapter = new HangoutsAdapter({\n    token: process.env.GOOGLE_TOKEN,\n    google_auth_params: {\n        credentials: process.env.GOOGLE_CREDS\n    }\n});\n\nconst server = restify.createServer();\nserver.use(restify.plugins.bodyParser());\nserver.post('/api/messages', (req, res) => {\n     adapter.processActivity(req, res, async(context) => {\n         await context.sendActivity('I heard a message!');\n     });\n});\n```\n\n## Class Reference\n\n* [HangoutsAdapter](../docs/reference/hangouts.md#hangoutsadapter)\n* [BotWorker Extensions](../docs/reference/hangouts.md#hangoutsbotworker)\n\n## Event List\n\nBotkit will emit the following events: \n\n| Event | Description\n|--- |---\n| message | a message from a user received in a shared channel\n| card_clicked | a user clicked a button on a card attachment\n| direct_message | a message from a user received in a private 1:1 with the bot\n| bot_room_join | the bot joined a new room\n| bot_dm_join | a new 1:1 with a user has been created\n| bot_room_leave | the bot has been removed from a room\n| bot_dm_leave | a 1:1 with a user has been closed\n\n## Calling Google APIs\n\nThis package exposes a pre-configured Google API client for developers who want to use one of the many available API endpoints.\n\nIn Botkit handlers, the `bot` worker object passed into all handlers will contain a `bot.api` field that contains the client, preconfigured and ready to use.\n\n```javascript\ncontroller.on('message', async(bot, message) {\n\n    // get a list of the members of a room\n    let members = await bot.api.spaces.members.get({name: message.channel});\n    // .. do stuff\n\n});\n```\n\n## Botkit Extensions\n\nIn Botkit handlers, the `bot` worker for Hangouts contains [all of the base methods](../docs/reference/core.md#BotWorker) as well as the following platform-specific extensions:\n\n### Use cards\n\nBotkit will automatically construct your outgoing messages according to Google's specifications. [Google Hangouts supports card attachments with buttons](https://developers.google.com/hangouts/chat/reference/message-formats/cards).\n\nTo use card attachments, add the `cards` field to the outgoing message object used to create the reply:\n\n```javascript\nawait bot.reply(message, {\n    text: 'Pick a card!',\n    cards: [\n        {\n            // card object\n        },\n    ]\n});\n```\n\n### Reply in a new thread\n\nIn Google Hangouts, messages are organized into threads. Botkit provides specialized methods for cases where a bot's reply should create a new thread, or for when a bot should conduct an entire conversation in new/separate thread.\n\n* [bot.replyInThread](../docs/reference/hangouts.md#replyinthread)\n* [bot.startConversationInThread](../docs/reference/hangouts.md#startconversationinthread)\n\n### Respond to `card_clicked` events\n\nWhen a button in an card attachment is clicked, Google sends a special event that requires a special response.  Botkit will emit a `card_clicked` event, which should be responded to using \neither `bot.replyWithUpdate()` or `bot.replyWithNew()`.\n\n[See Google doc for interactive cards &rarr;](https://developers.google.com/hangouts/chat/how-tos/cards-onclick#responding_to_clicks_with_a_new_or_updated_message).\n\n* [bot.replyWithUpdate](../docs/reference/hangouts.md#replywithupdate)\n* [bot.replyWithNew](../docs/reference/hangouts.md#relpywithnew)\n\n### Update and remove messages\n\nGoogle Hangouts supports updating and deleting messages. Do so with the following convenience methods:\n\n* [bot.updateMessage](../docs/reference/hangouts.md#updatemessage)\n* [bot.deleteMessage](../docs/reference/hangouts.md#deletemessage)\n\n\n## Community & Support\n\nJoin our thriving community of Botkit developers and bot enthusiasts at large.\nOver 10,000 members strong, [our open Slack group](https://community.botkit.ai) is\n_the place_ for people interested in the art and science of making bots.\nCome to ask questions, share your progress, and commune with your peers!\n\nYou can also find help from members of the Botkit team [in our dedicated Cisco Spark room](https://eurl.io/#SyNZuomKx)!\n\n## About Botkit\n\nBotkit is a part of the [Microsoft Bot Framework](https://dev.botframework.com).\n\nWant to contribute? [Read the contributor guide](https://github.com/howdyai/botkit/blob/master/CONTRIBUTING.md)\n\nBotkit is released under the [MIT Open Source license](https://github.com/howdyai/botkit/blob/master/LICENSE.md)"
  },
  {
    "path": "packages/botbuilder-adapter-hangouts/src/botworker.ts",
    "content": "/**\n * @module botbuilder-adapter-hangouts\n */\n/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { BotWorker, BotkitMessage } from 'botkit';\n\n/**\n * This is a specialized version of [Botkit's core BotWorker class](#BotWorker) that includes additional methods for interacting with Google Hangouts.\n * It includes all functionality from the base class, as well as the extension methods below.\n *\n * When using the HangoutsAdapter with Botkit, all `bot` objects passed to handler functions will include these extensions.\n */\nexport class HangoutsBotWorker extends BotWorker {\n    /**\n     * Access to the official [Google API client for Hangouts](https://www.npmjs.com/package/googleapis)\n     */\n    public api: any;\n\n    /**\n     * Update an existing message with new content.\n     *\n     * ```javascript\n     * // send a reply, capture the results\n     * let sent = await bot.reply(message,'this is my original reply...');\n     *\n     * // update the sent message using the sent.id field\n     * await bot.updateMessage({\n     *      id: sent.id,\n     *      text: 'this is an update!',\n     * })\n     * ```\n     *\n     * @param update An object in the form `{id: <id of message to update>, text: <new text>, card: <array of card objects>}`\n     */\n    public async updateMessage(update: Partial<BotkitMessage>): Promise<any> {\n        return this.controller.adapter.updateActivity(\n            this.getConfig('context'), // not currently used\n            {\n                id: update.id,\n                text: update.text,\n                channelData: {\n                    cards: update.cards\n                }\n            }\n        );\n    }\n\n    /**\n     * Delete an existing message.\n     *\n     * ```javascript\n     * // send a reply, capture the results\n     * let sent = await bot.reply(message,'this is my original reply...');\n     *\n     * // delete the sent message using the sent.id field\n     * await bot.deleteMessage(sent);\n     * ```\n     *\n     * @param update An object in the form of `{id: <id of message to delete>}`\n     */\n    public async deleteMessage(update: Partial<BotkitMessage>): Promise<any> {\n        return this.controller.adapter.deleteActivity(\n            this.getConfig('context'), // not currently used\n            {\n                activityId: update.id\n            }\n        );\n    }\n\n    /**\n     * Reply to a card_click event with a new message. [See Google doc for interactive cards &rarr;](https://developers.google.com/hangouts/chat/how-tos/cards-onclick#responding_to_clicks_with_a_new_or_updated_message).\n     *\n     * When a user clicks a button contained in a card attachment, a `card_clicked` event will be emitted.\n     * In order to reply to the incoming event with a new message (rather than replacing the original card), use this method!\n     *\n     * ```javascript\n     * controller.on('card_clicked', async(bot, message) => {\n     *      // check message.action.actionMethodName to see what button was clicked...\n     *      await bot.replyWithNew(message,'Reply to button click!');\n     * })\n     * ```\n     *\n     * @param src An incoming event object representing a card_clicked event\n     * @param resp A reply message containing text and/or cards\n     */\n    public async replyWithNew(src: any, resp: Partial<BotkitMessage>): Promise<any> {\n        resp = this.ensureMessageFormat(resp);\n        if (src.type === 'card_clicked') {\n            this.httpBody({\n                actionResponse: {\n                    type: 'NEW_MESSAGE'\n                },\n                text: resp.text,\n                cards: resp.channelData.cards\n            });\n        } else {\n            console.error('replyWithNew can only be used with card-click events');\n        }\n    }\n\n    /**\n     * Reply to a card_click event with an update to the original message. [See Google doc for interactive cards &rarr;](https://developers.google.com/hangouts/chat/how-tos/cards-onclick#responding_to_clicks_with_a_new_or_updated_message).\n     *\n     * When a user clicks a button contained in a card attachment, a `card_clicked` event will be emitted.\n     * In order to reply to the incoming event by replacing the original message, use this method!\n     *\n     * ```javascript\n     * controller.on('card_clicked', async(bot, message) => {\n     *      // check message.action.actionMethodName to see what button was clicked...\n     *      await bot.replyWithUpdate(message,'Reply to button click!');\n     * })\n     * ```\n     *\n     * @param src An incoming event object representing a card_clicked event\n     * @param resp A reply message containing text and/or cards\n     */\n    public async replyWithUpdate(src: any, resp: Partial<BotkitMessage>): Promise<any> {\n        resp = this.ensureMessageFormat(resp);\n        if (src.type === 'card_clicked') {\n            this.httpBody({\n                actionResponse: {\n                    type: 'UPDATE_MESSAGE'\n                },\n                text: resp.text,\n                cards: resp.cards\n            });\n        } else {\n            console.error('replyWithUpdate can only be used with card-click events');\n        }\n    }\n\n    /**\n     * Reply to an incoming message in a brand new thread.  Works for a single message reply - if multiple replies or replying with a dialog is necessary, use [startConversationInThread](#startconversationinthread).\n     *\n     * ```javascript\n     * controller.hears('thread','message', async(bot, message) =>{\n     *      await bot.replyInThread(message,'This will appear in a new thread.');\n     * });\n     * ```\n     * @param src An incoming message or event object\n     * @param resp A reply message containing text and/or cards\n     */\n    public async replyInThread(src, resp): Promise<any> {\n        // ensure that the threadKey is null.\n        // this will cause a new thread to be created.\n        delete src.incoming_message.conversation.thread;\n\n        // generate a random thread key id\n        src.incoming_message.conversation.threadKey = 'botkit/' + Math.random() * 100000 + '/' + Math.random() * 100000;\n\n        return this.reply(src, resp);\n    }\n\n    /**\n     * Switch the bot's active context to a new thread.\n     * Use this to change the location of a bot's responses or calls to beginDialog into a new conversation thread (rather than continuing in the same thread as the originating message)\n     *\n     * ```javascript\n     * controller.hears('new thread', 'message', async(bot, message) => {\n     *\n     *      // change to a new thread\n     *      await bot.startConversationInThread(message.channel, message.user);\n     *\n     *      // begin a dialog in the new thread\n     *      await bot.beginDialog('foo');\n     *\n     * });\n     * ```\n     *\n     * @param spaceName The name of the main space - usually `message.channel`\n     * @param userId The id of the user conducting the conversation - usually `message.user`\n     * @param threadKey An optional key definining the thread - if one is not provided, a random one is generated.\n     */\n    public async startConversationInThread(spaceName: string, userId: string, threadKey?: string): Promise<any> {\n        return this.changeContext({\n            conversation: {\n                id: spaceName,\n                // @ts-ignore we need to extend this object with additional fields\n                threadKey: threadKey || 'botkit/' + Math.random() * 100000 + '/' + Math.random() * 100000\n            },\n            user: { id: userId, name: null },\n            channelId: 'googlehangouts'\n        });\n    }\n}\n"
  },
  {
    "path": "packages/botbuilder-adapter-hangouts/src/hangouts_adapter.ts",
    "content": "/**\n * @module botbuilder-adapter-hangouts\n */\n/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { Activity, ActivityTypes, BotAdapter, TurnContext, ConversationReference, ResourceResponse } from 'botbuilder';\nimport * as Debug from 'debug';\nimport { google } from 'googleapis';\nimport { HangoutsBotWorker } from './botworker';\nconst debug = Debug('botkit:hangouts');\n\nconst apiVersion = 'v1';\n\n/**\n * Connect [Botkit](https://www.npmjs.com/package/botkit) or [BotBuilder](https://www.npmjs.com/package/botbuilder) to Google Hangouts\n *\n */\nexport class HangoutsAdapter extends BotAdapter {\n    /**\n     * Name used by Botkit plugin loader\n     * @ignore\n     */\n    public name = 'Google Hangouts Adapter';\n    /**\n     * Object containing one or more Botkit middlewares to bind automatically.\n     * @ignore\n     */\n    public middlewares;\n    /**\n     * A customized BotWorker object that exposes additional utility methods.\n     * @ignore\n     */\n    public botkit_worker = HangoutsBotWorker;\n\n    /**\n     * Location of configuration options.\n     */\n    private options: HangoutsAdapterOptions;\n\n    /**\n     * A copy of the Google Chat client.\n     */\n    private api: any;\n\n    /**\n     * Create an adapter to handle incoming messages from Google Hangouts and translate them into a standard format for processing by your bot.\n     *\n     * Use with Botkit:\n     *```javascript\n     * const adapter = new HangoutsAdapter({\n     *      token: process.env.GOOGLE_TOKEN,\n     *      google_auth_params: {\n     *          credentials: process.env.GOOGLE_CREDS\n     *      }\n     * });\n     * const controller = new Botkit({\n     *      adapter: adapter,\n     *      // ... other configuration options\n     * });\n     * ```\n     *\n     * Use with BotBuilder:\n     *```javascript\n     * const adapter = new HangoutsAdapter({\n     *      token: process.env.GOOGLE_TOKEN,\n     *      google_auth_params: {\n     *          credentials: process.env.GOOGLE_CREDS\n     *      }\n     * });\n     * // set up restify...\n     * const server = restify.createServer();\n     * server.use(restify.plugins.bodyParser());\n     * server.post('/api/messages', (req, res) => {\n     *      adapter.processActivity(req, res, async(context) => {\n     *          // do your bot logic here!\n     *      });\n     * });\n     * ```\n     *\n     * @param options An object containing API credentials and a webhook verification token\n     */\n    public constructor(options: HangoutsAdapterOptions) {\n        super();\n\n        this.options = options;\n\n        if (!this.options.token) {\n            const warning = [\n                '',\n                '****************************************************************************************',\n                '* WARNING: Your bot is operating without recommended security mechanisms in place.     *',\n                '* Initialize your adapter with a token parameter to enable                             *',\n                '* verification that all incoming webhooks originate with Google:                       *',\n                '*                                                                                      *',\n                '* var adapter = new HangoutsAdapter({token: <my secret from Google>});                 *',\n                '*                                                                                      *',\n                '****************************************************************************************',\n                '>> Official docs: https://developers.google.com/hangouts/chat/how-tos/bots-develop?hl=en_US#verifying_bot_authenticity',\n                ''\n            ];\n            console.warn(warning.join('\\n'));\n            if (!this.options.enable_incomplete) {\n                throw new Error('Required: include a verificationToken or clientSigningSecret to verify incoming Events API webhooks');\n            }\n        }\n\n        const params = {\n            scopes: 'https://www.googleapis.com/auth/chat.bot',\n            ...this.options.google_auth_params\n        };\n\n        google\n            .auth\n            .getClient(params)\n            .then(client => {\n                this.api = google.chat({ version: apiVersion, auth: client });\n            })\n            .catch(err => {\n                console.error('Could not get google auth client !');\n                if (!this.options.enable_incomplete) {\n                    throw new Error(err);\n                }\n            });\n\n        if (this.options.enable_incomplete) {\n            const warning = [\n                '',\n                '****************************************************************************************',\n                '* WARNING: Your adapter may be running with an incomplete/unsafe configuration.        *',\n                '* - Ensure all required configuration options are present                              *',\n                '* - Disable the \"enable_incomplete\" option!                                            *',\n                '****************************************************************************************',\n                ''\n            ];\n            console.warn(warning.join('\\n'));\n        }\n\n        this.middlewares = {\n            spawn: [\n                async (bot, next): Promise<void> => {\n                    bot.api = this.api;\n                    next();\n                }\n            ]\n        };\n    }\n\n    /**\n     * Formats a BotBuilder activity into an outgoing Hangouts event.\n     * @param activity A BotBuilder Activity object\n     */\n    private activityToHangouts(activity: Activity): any {\n        const message = {\n            parent: activity.conversation.id,\n            // @ts-ignore Ignore the presence of this unofficial field\n            threadKey: activity.conversation.threadKey || null,\n            requestBody: {\n                text: activity.text,\n                // @ts-ignore Ignore the presence of this unofficial field\n                thread: activity.conversation.thread ? { name: activity.conversation.thread } : null\n            }\n        };\n\n        // if channelData is specified, overwrite any fields in message object\n        if (activity.channelData) {\n            Object.keys(activity.channelData).forEach(function(key) {\n                message.requestBody[key] = activity.channelData[key];\n            });\n        }\n\n        debug('OUT TO HANGOUTS > ', message);\n\n        return message;\n    }\n\n    /**\n     * Standard BotBuilder adapter method to send a message from the bot to the messaging API.\n     * [BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#sendactivities).\n     * @param context A TurnContext representing the current incoming message and environment. (Not used)\n     * @param activities An array of outgoing activities to be sent back to the messaging API.\n     */\n    public async sendActivities(context: TurnContext, activities: Partial<Activity>[]): Promise<ResourceResponse[]> {\n        const responses = [];\n        for (let a = 0; a < activities.length; a++) {\n            const activity = activities[a] as Activity;\n            if (activity.type === ActivityTypes.Message) {\n                const message = this.activityToHangouts(activity);\n                try {\n                    const res = await this.api.spaces.messages.create(message);\n                    responses.push({ id: res.data.name });\n                } catch (err) {\n                    console.error('Error sending activity to API:', err);\n                }\n            } else {\n                // If there are ever any non-message type events that need to be sent, do it here.\n                debug('Unknown message type encountered in sendActivities: ', activity.type);\n            }\n        }\n\n        return responses;\n    }\n\n    /**\n     * Standard BotBuilder adapter method to update a previous message with new content.\n     * [BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#updateactivity).\n     * @param context A TurnContext representing the current incoming message and environment. (Not used)\n     * @param activity The updated activity in the form `{id: <id of activity to update>, text: <updated text>, cards?: [<array of updated hangouts cards>]}`\n     */\n    public async updateActivity(context: TurnContext, activity: Partial<Activity>): Promise<void> {\n        if (activity.id) {\n            try {\n                const results = await this.api.spaces.messages.update({\n                    name: activity.id,\n                    updateMask: 'text,cards',\n                    resource: {\n                        text: activity.text,\n                        // @ts-ignore allow cards field\n                        cards: activity.cards ? activity.cards : (activity.channelData ? activity.channelData.cards : null)\n                    }\n                });\n\n                if (!results || results.status !== 200) {\n                    throw new Error('updateActivity failed: ' + results.statusText);\n                }\n            } catch (err) {\n                console.error('Error updating activity on Hangouts.');\n                throw (err);\n            }\n        } else {\n            throw new Error('Cannot update activity: activity is missing id');\n        }\n    }\n\n    /**\n     * Standard BotBuilder adapter method to delete a previous message.\n     * [BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#deleteactivity).\n     * @param context A TurnContext representing the current incoming message and environment. (Not used)\n     * @param reference An object in the form `{activityId: <id of message to delete>}`\n     */\n    public async deleteActivity(context: TurnContext, reference: Partial<ConversationReference>): Promise<void> {\n        if (reference.activityId) {\n            try {\n                const results = await this.api.spaces.messages.delete({\n                    name: reference.activityId\n                });\n                if (!results || results.status !== 200) {\n                    throw new Error('deleteActivity failed: ' + results.statusText);\n                }\n            } catch (err) {\n                console.error('Error deleting activity', err);\n                throw err;\n            }\n        } else {\n            throw new Error('Cannot delete activity: reference is missing activityId');\n        }\n    }\n\n    /**\n     * Standard BotBuilder adapter method for continuing an existing conversation based on a conversation reference.\n     * [BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#continueconversation)\n     * @param reference A conversation reference to be applied to future messages.\n     * @param logic A bot logic function that will perform continuing action in the form `async(context) => { ... }`\n     */\n    public async continueConversation(reference: Partial<ConversationReference>, logic: (context: TurnContext) => Promise<void>): Promise<void> {\n        const request = TurnContext.applyConversationReference(\n            { type: 'event', name: 'continueConversation' },\n            reference,\n            true\n        );\n        const context = new TurnContext(this, request);\n\n        return this.runMiddleware(context, logic);\n    }\n\n    /**\n     * Accept an incoming webhook request and convert it into a TurnContext which can be processed by the bot's logic.\n     * @param req A request object from Restify or Express\n     * @param res A response object from Restify or Express\n     * @param logic A bot logic function in the form `async(context) => { ... }`\n     */\n    public async processActivity(req, res, logic: (context: TurnContext) => Promise<void>): Promise<void> {\n        const event = req.body;\n\n        debug('IN FROM HANGOUTS >', event);\n\n        if (this.options.token && this.options.token !== event.token) {\n            res.status(401);\n            debug('Token verification failed, Ignoring message');\n        } else {\n            const activity: Activity = {\n                id: event.message ? event.message.name : event.eventTime,\n                timestamp: new Date(),\n                channelId: 'googlehangouts',\n                conversation: {\n                    id: event.space.name,\n                    // @ts-ignore\n                    thread: (event.message && !event.threadKey) ? event.message.thread.name : null,\n                    // @ts-ignore\n                    threadKey: event.threadKey || null\n                },\n                from: {\n                    id: event.user.name,\n                    name: event.user.name\n                },\n                channelData: event,\n                text: event.message ? (event.message.argumentText ? event.message.argumentText.trim() : '') : '',\n                type: event.message ? ActivityTypes.Message : ActivityTypes.Event\n            };\n\n            // Change type of message event for private messages\n            if (event.space.type === 'DM') {\n                activity.channelData.botkitEventType = 'direct_message';\n            }\n\n            if (event.type === 'ADDED_TO_SPACE') {\n                activity.type = ActivityTypes.Event;\n                activity.channelData.botkitEventType = event.space.type === 'ROOM' ? 'bot_room_join' : 'bot_dm_join';\n            }\n\n            if (event.type === 'REMOVED_FROM_SPACE') {\n                activity.type = ActivityTypes.Event;\n                activity.channelData.botkitEventType = event.space.type === 'ROOM' ? 'bot_room_leave' : 'bot_dm_leave';\n            }\n\n            if (event.type === 'CARD_CLICKED') {\n                activity.type = ActivityTypes.Event;\n                activity.channelData.botkitEventType = event.type.toLowerCase();\n            }\n\n            // create a conversation reference\n            const context = new TurnContext(this, activity);\n\n            if (event.type !== 'CARD_CLICKED') {\n                // send 200 status immediately, otherwise\n                // hangouts does not mark the incoming message as received\n                res.status(200);\n                res.end();\n            } else {\n                context.turnState.set('httpStatus', 200);\n            }\n\n            await this.runMiddleware(context, logic);\n\n            if (event.type === 'CARD_CLICKED') {\n                // send http response back\n                res.status(context.turnState.get('httpStatus'));\n                if (context.turnState.get('httpBody')) {\n                    res.send(context.turnState.get('httpBody'));\n                } else {\n                    res.end();\n                }\n            }\n        }\n    }\n}\n\nexport interface HangoutsAdapterOptions {\n    /**\n     * Parameters passed to the [Google API client library](https://www.npmjs.com/package/googleapis) which is in turn used to send messages.\n     * Define credentials per [the GoogleAuthOptions defined here](https://github.com/googleapis/google-auth-library-nodejs/blob/master/src/auth/googleauth.ts#L54),\n     * OR, specify GOOGLE_APPLICATION_CREDENTIALS in environment [as described in the Google docs](https://cloud.google.com/docs/authentication/getting-started).\n     */\n    google_auth_params?: {\n        client_email?: string;\n        private_key?: string;\n    };\n    /**\n     * Shared secret token used to validate the origin of incoming webhooks.\n     * Get this from the [Google API console for your bot app](https://console.cloud.google.com/apis/api/chat.googleapis.com/hangouts-chat) - it is found on the Configuration tab under the heading \"Verification Token\".\n     * If defined, the origin of all incoming webhooks will be validated and any non-matching requests will be rejected.\n     */\n    token: string; // webhook validation token\n\n    /**\n     * Allow the adapter to startup without a complete configuration.\n     * This is risky as it may result in a non-functioning or insecure adapter.\n     * This should only be used when getting started.\n     */\n    enable_incomplete?: boolean;\n\n}\n"
  },
  {
    "path": "packages/botbuilder-adapter-hangouts/src/index.ts",
    "content": "/**\n * @module botbuilder-adapter-hangouts\n */\n/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport * from './hangouts_adapter';\n"
  },
  {
    "path": "packages/botbuilder-adapter-hangouts/tests/HangoutsAdapter.tests.js",
    "content": "const assert = require('assert');\nconst { HangoutsAdapter } = require('../');\n\ndescribe('HangoutsAdapter', function() {\n\n    let adapter;\n\n    // beforeEach(function () {\n    //     adapter = new HangoutsAdapter({\n    //         token: '123',\n    //     });\n    // });\n\n    it('should not construct without required parameters', function () {\n        assert.throws(function () { let adapter = new HangoutsAdapter({}) }, 'Foo');\n    });\n\n    // it('should create a HangoutsAdapter object', function () {\n    //     assert((adapter instanceof HangoutsAdapter), 'Adapter is wrong type');\n    // });\n\n});\n"
  },
  {
    "path": "packages/botbuilder-adapter-hangouts/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2015\",\n    \"module\": \"commonjs\",\n    \"declaration\": true,\n    \"sourceMap\": true,\n    \"outDir\": \"./lib\",\n    \"rootDir\": \"./src\",\n    \"types\" : [\"node\"],\n    \"lib\": [\n      \"es5\",\n      \"es2015\",\n      \"es2016.array.include\",\n      \"esnext.asynciterable\",\n      \"dom\"\n    ]\n  },\n  \"include\": [\n    \"src/**/*\"\n  ]\n}"
  },
  {
    "path": "packages/botbuilder-adapter-slack/.eslintrc.js",
    "content": "module.exports = {\n    \"extends\": \"standard\",\n    \"rules\": {\n        \"semi\": [2, \"always\"],\n        \"indent\": [2, 4],\n        \"no-return-await\": 0,\n        \"camelcase\": 0,\n        \"no-unused-vars\": 0,\n        \"@typescript-eslint/ban-ts-ignore\": 1,\n        \"@typescript-eslint/no-object-literal-type-assertion\": 0,\n        \"@typescript-eslint/indent\": 0,\n        \"@typescript-eslint/explicit-member-accessibility\": 1,\n        \"space-before-function-paren\": [2, {\n            \"named\": \"never\",\n            \"anonymous\": \"never\",\n            \"asyncArrow\": \"always\"\n        }],\n        \"template-curly-spacing\": [2, \"always\"]\n    }\n};"
  },
  {
    "path": "packages/botbuilder-adapter-slack/.gitignore",
    "content": "node_modules/\n.env\nlib/\n.nyc_output/\n"
  },
  {
    "path": "packages/botbuilder-adapter-slack/CHANGELOG.md",
    "content": "# botbuilder-adapter-slack changelog\n\n\n# 1.0.13\n\n* Update dependencies to Botkit 4.10, Bot Framework 4.10\n* Update @slack/web-api to 5.11.0\n\n\n# 1.0.12\n\n* Adjust startPrivateConversation to use converations.open instead of im.open\n\n\n# 1.0.11\n\n* Update dependencies to Botkit 4.9, Bot Framework 4.9\n* Fox: Remove enforcement of as_user field when using v2 oauth - Thanks to [@garytowers](https://github.com/GaryTowers) for [this pull request](https://github.com/howdyai/botkit/pull/1944).\n\n# 1.0.10\n\n* FIX: Fixing a bug introduced in 4.8 pertaining to spawning proactive bots for Slack. [#1937](https://github.com/howdyai/botkit/issues/1937)\n\n# 1.0.9\n\n* Update @slack/web-api to 5.8.0 \n* Add `oauthVersion` parameter to constructor. If set to `v2`, oauth features will use Slack's latest auth functions and urls. [More info](readme.md#using-slacks-v2-oauth)\n* Make `authed_users` field available. [Fix for #1911](https://github.com/howdyai/botkit/issues/1911)\n\n# 1.0.8\n\n* Update @slack/web-api to 5.7.0 which includes access to new Oauth features (see [#1890](https://github.com/howdyai/botkit/pull/1890))\n* Make `redirectUri` optional in type definition - thanks @yakirn [#1895](https://github.com/howdyai/botkit/pull/1895/files)\n\n# 1.0.7\n\n* Update @slack/web-api to 5.5.0\n\n# 1.0.6\n\n* Update dependencies (Bot Framework to 4.6, Botkit to 4.6)\n\n# 1.0.5\n\n* Add support for using the new [Block Kit modals](https://api.slack.com/block-kit/surfaces/modals).  Check out [this sample code for examples of using them](https://github.com/howdyai/botkit/blob/master/packages/testbot/features/slack_modals.js).\n* Update to the latest version of the [@slack/web-api](https://www.npmjs.com/package/@slack/web-api), granting access to recently added methods like views.open, views.update\n* Fix: previous versions incorrectly labeled incoming `block_actions` and `interactive_message` events as `message` events. This version corrects this - `controller.on('block_actions',...)` and `controller.hears(pattern,'block_actions',...)` should now work.\n* Expand ability to \"hear\" block actions and use them in conversations. Selections from dropdowns and datepickers can now be heard by the bot and will be included as `message.text` in incoming messages.  Thanks to [@sfny](https://github.com/sfny) for the [pull request](https://github.com/howdyai/botkit/pull/1809)\n\n\n# 1.0.4\n\n* Update dependencies (Bot Framework to 4.5.2, Botkit to 4.5)\n* Block actions and interactive button clicks are now classified as \"message\" type events, and thus included in conversations\n* Update some type definitions in the Slack Dialog class.\n\n\n# 1.0.3\n\n* Fix typo in replyInteractive - Thanks to [@VictorGrycuk](https://github.com/VictorGrycuk) for [the fix](https://github.com/howdyai/botkit/pull/1650)\n* Fix for handling some events that do not have a channel id - Thanks to [@roger-king](https://github.com/roger-king) and [@jebarjonet](https://github.com/jebarjonet) for help [trackign this down](https://github.com/howdyai/botkit/issues/1641)\n* Update Typedef of Slack dialog options - Thanks to [@roger-king](https://github.com/roger-king)  for [the fix](https://github.com/howdyai/botkit/pull/1653)\n* Add `enable_incomplete` option to allow adapter to start without a complete config.\n\n# 1.0.2\n\n* Fix for [getInstallLink()](https://github.com/howdyai/botkit/pull/1642) - now includes redirectUri if set.  Thanks to [@jebarjonet](https://github.com/jebarjonet) for the fix.\n* Fix to TypeScript definition, - Thanks to [@roger-king](https://github.com/roger-king) for [this contribution](https://github.com/howdyai/botkit/pull/1634).\n\n# 1.0.1\n\nThis was the first public release!\n"
  },
  {
    "path": "packages/botbuilder-adapter-slack/LICENSE.md",
    "content": "Copyright XOXCO, Inc, http://xoxco.com, http://howdy.ai\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "packages/botbuilder-adapter-slack/examples/index.js",
    "content": "// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nconst restify = require('restify');\nconst path = require('path');\n\n// Import required bot services. See https://aka.ms/bot-services to learn more about the different part of a bot\nconst { MemoryStorage, ConversationState, UserState, TurnContext } = require('botbuilder');\nconst { BotConfiguration } = require('botframework-config');\n\nconst { SlackAdapter, SlackEventMiddleware, SlackIdentifyBotsMiddleware } = require('../lib/slack_adapter');\n\n// Read botFilePath and botFileSecret from .env file\n// Note: Ensure you have a .env file and include botFilePath and botFileSecret.\nconst ENV_FILE = path.join(__dirname, '.env');\nrequire('dotenv').config({ path: ENV_FILE });\n\n// Create HTTP server\nlet server = restify.createServer();\nserver.use(restify.plugins.bodyParser({ mapParams: false }));\nserver.use(restify.plugins.queryParser());\nserver.listen(process.env.port || process.env.PORT || 3978, function() {\n    console.log(`\\n${ server.name } listening to ${ server.url }`);\n    console.log(`\\nGet Bot Framework Emulator: https://aka.ms/botframework-emulator`);\n});\n\n// .bot file path\nconst BOT_FILE = path.join(__dirname, (process.env.botFilePath || ''));\n\nlet botConfig;\ntry {\n    // Read bot configuration from .bot file.\n    botConfig = BotConfiguration.loadSync(BOT_FILE, process.env.botFileSecret);\n} catch (err) {\n    console.error(`\\nError reading bot file. Please ensure you have valid botFilePath and botFileSecret set for your environment.`);\n    console.error(`\\n - The botFileSecret is available under appsettings for your Azure Bot Service bot.`);\n    console.error(`\\n - If you are running this bot locally, consider adding a .env file with botFilePath and botFileSecret.\\n\\n`);\n    process.exit();\n}\n\nconst DEV_ENVIRONMENT = 'development';\n\n// bot name as defined in .bot file\n// See https://aka.ms/about-bot-file to learn more about .bot file its use and bot configuration.\nconst BOT_CONFIGURATION = (process.env.NODE_ENV || DEV_ENVIRONMENT);\n\n// Get bot endpoint configuration by service name\nconst endpointConfig = botConfig.findServiceByNameOrId(BOT_CONFIGURATION);\n\nconst adapter = new SlackAdapter({\n    verificationToken: process.env.verificationToken,\n    botToken: process.env.botToken,\n    // oauthToken: process.env.oauthToken,\n    // getTokenForTeam: async (teamId) => {\n    //     return process.env.botToken;\n    // },\n    debug: true\n});\n\n// Use SlackEventMiddleware to modify incoming Activity objects so they have .type fields that match their original Slack event types.\nadapter.use(new SlackEventMiddleware());\n\n// Use SlackIdentifyBotsMiddleware to get a bot's real user id in the from field, as well as identify messages originating from THIS bot.\n// Is this actual useful? Who needs self_messages?\n// adapter.use(new SlackIdentifyBotsMiddleware());\n\n// Load typing middleware\n// adapter.use(new ShowTypingMiddleware(2000,4000));\n\n// Define state store for your bot. See https://aka.ms/about-bot-state to learn more about using MemoryStorage.\n// A bot requires a some sort of state storage system to persist the dialog and user state between messages.\nconst memoryStorage = new MemoryStorage();\n\n// CAUTION: You must ensure your product environment has the NODE_ENV set\n//          to use the Azure Blob storage or Azure Cosmos DB providers.\n// const { BlobStorage } = require('botbuilder-azure');\n// Storage configuration name or ID from .bot file\n// const STORAGE_CONFIGURATION_ID = '<STORAGE-NAME-OR-ID-FROM-BOT-FILE>';\n// // Default container name\n// const DEFAULT_BOT_CONTAINER = '<DEFAULT-CONTAINER>';\n// // Get service configuration\n// const blobStorageConfig = botConfig.findServiceByNameOrId(STORAGE_CONFIGURATION_ID);\n// const blobStorage = new BlobStorage({\n//     containerName: (blobStorageConfig.container || DEFAULT_BOT_CONTAINER),\n//     storageAccountOrConnectionString: blobStorageConfig.connectionString,\n// });\n\n// Create conversation state with in-memory storage provider.\nconst conversationState = new ConversationState(memoryStorage);\nconst userState = new UserState(memoryStorage);\n\n// Listen for incoming requests.\nserver.post('/api/messages', (req, res) => {\n    adapter.processActivity(req, res, async (context) => {\n        if (context.activity.type === 'message') {\n            if (context.activity.text === 'delayed') {\n                await context.sendActivity('give me 10 seconds....');\n                await respondDelayed(context);\n            } else if (context.activity.text === 'delete') {\n                const outgoing = await context.sendActivity('This message will self destruct in a few seconds!');\n                // console.log('outgoing id:', outgoing);\n                var reference = TurnContext.getConversationReference(context.activity);\n                setTimeout(async () => {\n                    await adapter.continueConversation(reference, async function(new_context) {\n                        adapter.deleteActivity(new_context, outgoing);\n                    });\n                }, 5000);\n            } else if (context.activity.text === 'update') {\n                const outgoing = await context.sendActivity('This message will be updated in a few seconds!');\n                // console.log('outgoing id:', outgoing);\n                var reference = TurnContext.getConversationReference(context.activity);\n                setTimeout(async () => {\n                    await adapter.continueConversation(reference, async function(new_context) {\n                        var update = {\n                            text: 'This has been updated',\n                            ...outgoing\n                        }\n                        const activity = TurnContext.applyConversationReference(update, reference);\n                        adapter.updateActivity(new_context, activity);\n                    });\n                }, 5000);\n            } else {\n                await context.sendActivity({\n                    text: 'Heard: ' + context.activity.text,\n                    channelData: {\n                        attachments: [\n                            {\n                                title: 'Options',\n                                callback_id: '123',\n                                actions: [\n                                    {\n                                        name: 'ok_button',\n                                        text: 'OK',\n                                        value: true,\n                                        type: 'button'\n                                    }\n                                ]\n                            }\n                        ]\n                    }\n                });\n            }\n        } else {\n            // console.log('EVENT:', context.activity.type);\n            if (context.activity.type === 'interactive_message') {\n                const slack = await adapter.getAPI(context.activity);\n                slack.dialog.open({\n                    trigger_id: context.activity.channelData.trigger_id,\n                    dialog: {\n                        'callback_id': 'ryde-46e2b0',\n                        'title': 'Request a Ride',\n                        'submit_label': 'Request',\n                        'notify_on_cancel': true,\n                        'state': 'Limo',\n                        'elements': [\n                            {\n                                'type': 'text',\n                                'label': 'Pickup Location',\n                                'name': 'loc_origin'\n                            },\n                            {\n                                'type': 'text',\n                                'label': 'Dropoff Location',\n                                'name': 'loc_destination'\n                            }\n                        ]\n                    }\n                });\n            } else if (context.activity.type === 'dialog_submission') {\n                console.log('DIALOG SUBMISSION:', context.activity.channelData.submission);\n            } else if (context.activity.type === 'self_bot_message') {\n                console.log('I CAN HEAR MYSELF TALKING!!!');\n            }\n        }\n    });\n});\n\n// Catch-all for errors.\nadapter.onTurnError = async (context, error) => {\n    // This check writes out errors to console log .vs. app insights.\n    console.error(`\\n [onTurnError]: ${ error }`);\n    // Send a message to the user\n    context.sendActivity(`Oops. Something went wrong!`);\n    // Clear out state\n    conversationState.clear(context);\n};\n\nasync function respondDelayed(context) {\n    var reference = TurnContext.getConversationReference(context.activity);\n    // console.log('GOT A REFERENCE', reference);\n    setTimeout(async function() {\n        // console.log('FIRING DELAYED CONTINUE');\n        await adapter.continueConversation(reference, async function(new_context) {\n            // console.log('GOT A NEW CONTEXT');\n            await new_context.sendActivity('I waited 10 seconds to tell you this.');\n        });\n    }, 10000);\n}\n"
  },
  {
    "path": "packages/botbuilder-adapter-slack/examples/multiteam.js",
    "content": "// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nconst restify = require('restify');\nconst path = require('path');\n\n// Import required bot services. See https://aka.ms/bot-services to learn more about the different part of a bot\nconst { MemoryStorage, ConversationState, UserState, TurnContext } = require('botbuilder');\nconst { BotConfiguration } = require('botframework-config');\n\nconst { SlackAdapter, SlackEventMiddleware, SlackIdentifyBotsMiddleware } = require('../lib/slack_adapter');\n\n// Read botFilePath and botFileSecret from .env file\n// Note: Ensure you have a .env file and include botFilePath and botFileSecret.\nconst ENV_FILE = path.join(__dirname, '.env');\nrequire('dotenv').config({ path: ENV_FILE });\n\n// Create HTTP server\nlet server = restify.createServer();\nserver.use(restify.plugins.bodyParser({ mapParams: false }));\nserver.use(restify.plugins.queryParser());\nserver.listen(process.env.port || process.env.PORT || 3978, function() {\n    console.log(`\\n${ server.name } listening to ${ server.url }`);\n    console.log(`\\nGet Bot Framework Emulator: https://aka.ms/botframework-emulator`);\n});\n\n// .bot file path\nconst BOT_FILE = path.join(__dirname, (process.env.botFilePath || ''));\n\nlet botConfig;\ntry {\n    // Read bot configuration from .bot file.\n    botConfig = BotConfiguration.loadSync(BOT_FILE, process.env.botFileSecret);\n} catch (err) {\n    console.error(`\\nError reading bot file. Please ensure you have valid botFilePath and botFileSecret set for your environment.`);\n    console.error(`\\n - The botFileSecret is available under appsettings for your Azure Bot Service bot.`);\n    console.error(`\\n - If you are running this bot locally, consider adding a .env file with botFilePath and botFileSecret.\\n\\n`);\n    process.exit();\n}\n\nconst DEV_ENVIRONMENT = 'development';\n\n// bot name as defined in .bot file\n// See https://aka.ms/about-bot-file to learn more about .bot file its use and bot configuration.\nconst BOT_CONFIGURATION = (process.env.NODE_ENV || DEV_ENVIRONMENT);\n\n// Get bot endpoint configuration by service name\nconst endpointConfig = botConfig.findServiceByNameOrId(BOT_CONFIGURATION);\n\nconst adapter = new SlackAdapter({\n    verificationToken: process.env.verificationToken,\n    clientId: process.env.clientId,\n    clientSecret: process.env.clientSecret,\n    scopes: ['bot'],\n    redirectUri: process.env.redirectUri,\n    getTokenForTeam: getTokenForTeam,\n    debug: true\n});\n\n// Use SlackEventMiddleware to modify incoming Activity objects so they have .type fields that match their original Slack event types.\nadapter.use(new SlackEventMiddleware());\n\n// Use SlackIdentifyBotsMiddleware to get a bot's real user id in the from field, as well as identify messages originating from THIS bot.\n// Is this actual useful? Who needs self_messages?\n// adapter.use(new SlackIdentifyBotsMiddleware());\n\n// Load typing middleware\n// adapter.use(new ShowTypingMiddleware(2000,4000));\n\n// Define state store for your bot. See https://aka.ms/about-bot-state to learn more about using MemoryStorage.\n// A bot requires a some sort of state storage system to persist the dialog and user state between messages.\nconst memoryStorage = new MemoryStorage();\n\n// CAUTION: You must ensure your product environment has the NODE_ENV set\n//          to use the Azure Blob storage or Azure Cosmos DB providers.\n// const { BlobStorage } = require('botbuilder-azure');\n// Storage configuration name or ID from .bot file\n// const STORAGE_CONFIGURATION_ID = '<STORAGE-NAME-OR-ID-FROM-BOT-FILE>';\n// // Default container name\n// const DEFAULT_BOT_CONTAINER = '<DEFAULT-CONTAINER>';\n// // Get service configuration\n// const blobStorageConfig = botConfig.findServiceByNameOrId(STORAGE_CONFIGURATION_ID);\n// const blobStorage = new BlobStorage({\n//     containerName: (blobStorageConfig.container || DEFAULT_BOT_CONTAINER),\n//     storageAccountOrConnectionString: blobStorageConfig.connectionString,\n// });\n\n// Create conversation state with in-memory storage provider.\nconst conversationState = new ConversationState(memoryStorage);\nconst userState = new UserState(memoryStorage);\n\nconst tokenCache = [];\nasync function getTokenForTeam(teamId) {\n    if (tokenCache[teamId]) {\n        return tokenCache[teamId];\n    } else {\n        console.error('Team not found in tokenCache: ', teamId);\n    }\n}\n\nserver.get('/install', (req, res) => {\n    // getInstallLink points to slack's oauth endpoint and includes clientId and scopes\n    res.redirect(adapter.getInstallLink(), function() {\n        res.end();\n    });\n});\n\nserver.get('/install/auth', async (req, res) => {\n    try {\n        const results = await adapter.validateOauthCode(req.query.code);\n\n        // Store token by team in bot state.\n        tokenCache[results.team_id] = results.bot.bot_access_token;\n\n        // TODO: NEED TO ALSO CAPTURE BOT ID USER ID\n        // THIS WILL LET US DO DIRECT_MENTION, SELF_MESSAGE, ETC\n\n        res.json('Success! Bot installed.');\n\n    } catch (err) {\n        console.error('OAUTH ERROR:', err);\n        res.status(401);\n        res.send(err.message);\n    }\n});\n\n// Listen for incoming requests.\nserver.post('/api/messages', (req, res) => {\n    adapter.processActivity(req, res, async (context) => {\n        if (context.activity.type === 'message') {\n            if (context.activity.text === 'delayed') {\n                await context.sendActivity('give me 10 seconds....');\n                await respondDelayed(context);\n            } else if (context.activity.text === 'delete') {\n                const outgoing = await context.sendActivity('This message will self destruct in a few seconds!');\n                // console.log('outgoing id:', outgoing);\n                var reference = TurnContext.getConversationReference(context.activity);\n                setTimeout(async () => {\n                    await adapter.continueConversation(reference, async function(new_context) {\n                        adapter.deleteActivity(new_context, outgoing);\n                    });\n                }, 5000);\n            } else if (context.activity.text === 'update') {\n                const outgoing = await context.sendActivity('This message will be updated in a few seconds!');\n                // console.log('outgoing id:', outgoing);\n                var reference = TurnContext.getConversationReference(context.activity);\n                setTimeout(async () => {\n                    await adapter.continueConversation(reference, async function(new_context) {\n                        adapter.updateActivity(new_context, {text: 'This has been updated!', ...outgoing});\n                    });\n                }, 5000);\n            } else {\n                await context.sendActivity({\n                    text: 'Heard: ' + context.activity.text,\n                    channelData: {\n                        attachments: [\n                            {\n                                title: 'Options',\n                                callback_id: '123',\n                                actions: [\n                                    {\n                                        name: 'ok_button',\n                                        text: 'OK',\n                                        value: true,\n                                        type: 'button'\n                                    }\n                                ]\n                            }\n                        ]\n                    }\n                });\n            }\n        } else {\n            // console.log('EVENT:', context.activity.type);\n            if (context.activity.type === 'interactive_message') {\n                const slack = await adapter.getAPI(context.activity);\n                slack.dialog.open({\n                    trigger_id: context.activity.channelData.trigger_id,\n                    dialog: {\n                        'callback_id': 'ryde-46e2b0',\n                        'title': 'Request a Ride',\n                        'submit_label': 'Request',\n                        'notify_on_cancel': true,\n                        'state': 'Limo',\n                        'elements': [\n                            {\n                                'type': 'text',\n                                'label': 'Pickup Location',\n                                'name': 'loc_origin'\n                            },\n                            {\n                                'type': 'text',\n                                'label': 'Dropoff Location',\n                                'name': 'loc_destination'\n                            }\n                        ]\n                    }\n                });\n            } else if (context.activity.type === 'dialog_submission') {\n                console.log('DIALOG SUBMISSION:', context.activity.channelData.submission);\n            } else if (context.activity.type === 'self_bot_message') {\n                console.log('I CAN HEAR MYSELF TALKING!!!');\n            }\n        }\n    });\n});\n\n// Catch-all for errors.\nadapter.onTurnError = async (context, error) => {\n    // This check writes out errors to console log .vs. app insights.\n    console.error(`\\n [onTurnError]: ${ error }`);\n    // Send a message to the user\n    context.sendActivity(`Oops. Something went wrong!`);\n    // Clear out state\n    conversationState.clear(context);\n};\n\nasync function respondDelayed(context) {\n    var reference = TurnContext.getConversationReference(context.activity);\n    // console.log('GOT A REFERENCE', reference);\n    setTimeout(async function() {\n        // console.log('FIRING DELAYED CONTINUE');\n        await adapter.continueConversation(reference, async function(new_context) {\n            // console.log('GOT A NEW CONTEXT');\n            await new_context.sendActivity('I waited 10 seconds to tell you this.');\n        });\n    }, 10000);\n}\n"
  },
  {
    "path": "packages/botbuilder-adapter-slack/package.json",
    "content": "{\n  \"name\": \"botbuilder-adapter-slack\",\n  \"version\": \"1.0.14\",\n  \"description\": \"Connect Botkit or BotBuilder to Slack\",\n  \"main\": \"./lib/index.js\",\n  \"typings\": \"./lib/index.d.ts\",\n  \"files\": [\n    \"/lib\",\n    \"/src\"\n  ],\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"test\": \"tsc ; nyc mocha tests/*.tests.js\",\n    \"eslint\": \"./node_modules/.bin/eslint --fix src/*\",\n    \"pack\": \"npm pack\"\n  },\n  \"author\": \"Microsoft Corp.\",\n  \"license\": \"MIT\",\n  \"keywords\": [\n    \"slack\",\n    \"botkit\",\n    \"botbuilder\",\n    \"botframework\",\n    \"bots\",\n    \"chatbots\",\n    \"azure\"\n  ],\n  \"homepage\": \"https://github.com/howdyai/botkit/blob/master/packages/botbuilder-adapter-slack#readme\",\n  \"bugs\": {\n    \"url\": \"https://github.com/howdyai/botkit/issues\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/howdyai/botkit.git\"\n  },\n  \"dependencies\": {\n    \"@slack/web-api\": \"^6.5.1\",\n    \"botbuilder\": \"^4.15.0\",\n    \"botkit\": \"^4.15.0\",\n    \"debug\": \"^4.1.0\"\n  },\n  \"devDependencies\": {\n    \"eslint\": \"^8.3.0\",\n    \"eslint-config-standard\": \"^16.0.3\",\n    \"eslint-plugin-import\": \"^2.25.3\",\n    \"eslint-plugin-node\": \"^11.1.0\",\n    \"eslint-plugin-promise\": \"^5.1.1\",\n    \"eslint-plugin-standard\": \"^4.0.1\"\n  }\n}\n"
  },
  {
    "path": "packages/botbuilder-adapter-slack/readme.md",
    "content": "# botbuilder-adapter-slack\n\nConnect [Botkit](https://www.npmjs.com/package/botkit) or [BotBuilder](https://www.npmjs.com/package/botbuilder) to Slack.\n\nThis package contains an adapter that communicates directly with the Slack API,\nand translates messages to and from a standard format used by your bot. This package can be used alongside your favorite bot development framework to build bots that work with Slack.\n\n## Install Package\n\nAdd this package to your project using npm:\n\n```bash\nnpm install --save botbuilder-adapter-slack\n```\n\nImport the adapter class into your code:\n\n```javascript\nconst { SlackAdapter } = require('botbuilder-adapter-slack');\n```\n\n## Get Started\n\nIf you are starting a brand new project, [follow these instructions to create a customized application template.](../docs/index.md)\n\n## Use SlackAdapter in your App\n\nSlackAdapter provides a translation layer for Botkit and BotBuilder so that bot developers can connect to Slack and have access to the Slack's API.\n\n### Botkit Basics\n\nWhen used in concert with Botkit, developers need only pass the configured adapter to the Botkit constructor, as seen below. Botkit will automatically create and configure the webhook endpoints and other options necessary for communicating with Slack.\n\nDevelopers can then bind to Botkit's event emitting system using `controller.on` and `controller.hears` to filter and handle incoming events from the messaging platform. [Learn more about Botkit's core feature &rarr;](../docs/index.md).\n\n[A full description of the SlackAdapter options and example code can be found in the class reference docs.](../docs/reference/slack.md#create-a-new-slackadapter)\n\n```javascript\nconst adapter = new SlackAdapter({\n    clientSigningSecret: process.env.SLACK_SECRET,\n    botToken: process.env.SLACK_TOKEN\n});\n\nconst controller = new Botkit({\n    adapter,\n    // ...other options\n});\n\ncontroller.on('message', async(bot, message) => {\n    await bot.reply(message, 'I heard a message!');\n});\n```\n\n### BotBuilder Basics\n\nAlternately, developers may choose to use `SlackAdapter` with BotBuilder. With BotBuilder, the adapter is used more directly with a webserver, and all incoming events are handled as [Activities](https://docs.microsoft.com/en-us/javascript/api/botframework-schema/activity?view=botbuilder-ts-latest).\n\n```javascript\nconst adapter = new SlackAdapter({\n    clientSigningSecret: process.env.SLACK_SECRET,\n    botToken: process.env.SLACK_TOKEN\n});\n\nconst server = restify.createServer();\nserver.use(restify.plugins.bodyParser());\nserver.post('/api/messages', (req, res) => {\n     adapter.processActivity(req, res, async(context) => {\n         await context.sendActivity('I heard a message!');\n     });\n});\n```\n\n### Important URLs\n\nYour bot application will present several important URLs. You'll need to configure your Slack application profile with these urls.\n\nThe messaging endpoint, which receives all events from Slack is: `https://YOURBOT/api/messages`\n\nThe default \"install\" URL that triggers the oauth flow for multi-team installation is `https://YOURBOT/install`\n\nThe oauth callback URL (or \"redirect uri\") that should be added to your Slack application profile is `https://YOURBOT/install/auth`\n\n### Multi-team Support\n\nIn the examples above, the `SlackAdapter` constructor received a single `botToken` parameters. This binds the adapter and all API calls it makes to a single Slack workspace.\n\nTo use `SlackAdapter` with multiple Slack workspaces, the constructor must receive a a different set of parameters. These parameters allow the adapter to be configured to work as an oauth client application of Slack's API, and will expose an \"install link\" used to add the application to each Slack workspace.\n\nIn additionto fields related to oauth, the constructor must also receive 2 functions:\n\n* a parameter named `getTokenForTeam` that is responsible for returning a token value when provided a Slack workspace ID.\n* a parameter named `getBotUserByTeam` that is responsible for returning a bot's user id value when provided a Slack workspace ID.\n\nThe application must implement its own mechanism for securely storing and retrieving these values.\n\n```javascript\nconst adapter = new SlackAdapter({\n    clientSigningSecret: process.env.SLACK_SECRET,\n    clientId: process.env.CLIENT_ID, // oauth client id\n    clientSecret: process.env.CLIENT_SECRET, // oauth client secret\n    scopes: ['bot'], // oauth scopes requested, 'bot' deprecated by Slack in favor of granular permissions\n    redirectUri: process.env.REDIRECT_URI, // url to redirect post-login\n    oauthVersion: 'v1', // or use v2\n    getTokenForTeam: async(team_id) => {\n        // load the token for this team\n        // as captured during oauth \n    }, \n    getBotUserByTeam: async(team_id) = {\n        // load bot user id for this team   \n        // as captured during oauth \n    }\n});\n\n// Create a route for the install link.\n// This will redirect the user to Slack's permission request page.\ncontroller.webserver.get('/install', (req, res) => {\n    res.redirect(adapter.getInstallLink());\n});\n\n// Create a route to capture the results of the oauth flow.\n// this URL should match the value of the `redirectUri` passed to Botkit.\ncontroller.webserver.get('/install/auth', (req, res) => {\n    try {\n        const results = await controller.adapter.validateOauthCode(req.query.code);\n\n        // Store token by team in bot state.\n        let team = results.team_id; // results.team.id in oauth v2\n        let token = results.bot.bot_access_token; // results.access_token in oauth v2\n        let userId = results.bot.bot_user_id; // results.bot_user_id in oauth v2\n\n        // Securely store the token and usedId so that they can be retrieved later by the team id.\n        // ...\n\n        // customize your post-install success page\n        res.send('Success! Bot installed.');\n\n    } catch (err) {\n        console.error('OAUTH ERROR:', err);\n        // customize your post-install failure page\n        res.status(401);\n        res.send(err.message);\n    }\n});\n```\n\n### Using Slack's v2 OAuth\n\nTo use Slack's [newer \"granular scopes\"](https://api.slack.com/authentication/oauth-v2), specify `oauthVersion: 'v2'` in your adapter configuration.\nThis will cause the adapter to use the v2 oauth URL and credential validation function.\nHowever, note that the payload returned `validateOauthCode` differs between versions.\n\nIn v1, your bot's token will be located at `results.bot.bot_access_token`, whereas in v2, it will be `results.access_token`.\n\nIn v1, your bot's user id will be at `results.bot.bot_user_id`, whereas in v2 it will be `results.bot_user_id`.\n\nFrom Slack's official docs:\n\n* [V1 response payload](https://api.slack.com/methods/oauth.access#response)\n* [V2 response payload](https://api.slack.com/methods/oauth.v2.access#response)\n\nTake care to update your auth handler function when you migrate to granular scopes.\n\n## Class Reference\n\n* [SlackAdapter](../docs/reference/slack.md#slackadapter)\n* [BotWorker Extensions](../docs/reference/slack.md#slackbotworker)\n* [SlackMessageTypeMiddleware](../docs/reference/slack.md#slackmessagetypemiddleware)\n* [SlackEventMiddleware](../docs/reference/slack.md#slackeventmiddleware)\n\n\n## Event List\n\nBotkit will emit the following events: \n\n| Event | Description\n|--- |---\n| message | a message from a user received in a shared channel\n| event | all other events from Slack (unless middlewares enabled, see below)\n\nThis package includea a set of optional middleware that will modify the type of incoming events to match their Slack event types (rather than being cast into generic \"message or \"event\" types).\n\nMost Botkit developers who plan to use features above and beyond the basic send/receive API should enable these middleware.\n\nImport the adapter and the middlewares:\n\n```javascript\n// load SlackAdapter AND SlackEventMiddleware\nconst { SlackAdapter, SlackEventMiddleware, SlackMessageTypeMiddleware } = require('botbuilder-adapter-slack');\n```\n\nCreate your adapter (as above), then bind the middlewares to the adapter:\n\n```javascript\nadapter.use(new SlackEventMiddleware());\nadapter.use(new SlackMessageTypeMiddleware());\n```\n\nNow, Botkit will emit events with their original Slack names:\n\n```\ncontroller.on('channel_join', async(bot, message) => {\n    // do stuff\n});\n```\n\n## Calling Slack APIs\n\nThis package exposes a pre-configured [Slack API client](https://slack.dev/node-slack-sdk/web-api) for developers who want to use one of the many available API endpoints.\n\nIn Botkit handlers, the `bot` worker object passed into all handlers will contain a `bot.api` field that contains the client, preconfigured and ready to use.\n\n```javascript\ncontroller.on('message', async(bot, message) {\n\n    // load a user profile\n    let profile = await bot.api.users.info({user: message.user});\n\n});\n```\n\n## Botkit Extensions\n\nIn Botkit handlers, the `bot` worker for Slack contains [all of the base methods](../docs/reference/core.md#BotWorker) as well as the following platform-specific extensions:\n\n### [controller.getInstallLink()](../docs/reference/slack.md#getinstalllink)\n\nReturns the first step of an oauth-flow that results in the Botkit application being enabled on a workspace.\nUse this in concert with [multi-team support](#multi-team-support).\n\n### [controller.validateOauthCode()](../docs/reference/slack.md#validateoauthcode)\n\nThis method receives the oauth code returned by Slack at the end of the oauth-flow and returns all of the credentials and authentication details associated with it.  Use this to capture the workspace token and bot user ID needed for multi-team support.\n\n### Use attachments, blocks, and other rich message features\n\nBotkit will automatically construct your outgoing messages according to Slack's specifications. To use attachments, blocks or other features, add them to the message object used to create the reply.\n\n**Use Block Kit Blocks**\n\nThe preferred way of composing interactive messages is using Slack's Block Kit.  [Read the official Slack documentation here](https://api.slack.com/messaging/composing/layouts). Slack provides a UI to help create your interactive messages. Check out [Block Kit Builder](https://api.slack.com/tools/block-kit-builder).\n\nAdditionally, there are open-source libraries available that assist with building out UIs for Slack:\n\n* [**Block Builder**](https://github.com/raycharius/slack-block-builder) – Zero-dependency library, with a SwiftUI-like builder syntax.\n* [**JSX-Slack**](https://github.com/speee/jsx-slack) – JSX that transpiles to Slack API-compatible JSON.\n\nInteractive messages using blocks can be sent via any of Botkit's built in functions by passing in the appropriate \"blocks\" as part of the message.  Here is an example:\n\n```javascript\nconst content = {\n    blocks: [{...}]; // insert valid JSON following Block Kit specs\n};\n\nawait bot.reply(message, content);\n```\n\n**Use \"Secondary\" Attachments**\n\nAttachments are still supported by Slack, but the preferred way is to use Block Kit. [Read the official Slack documentation here](https://api.slack.com/reference/messaging/attachments)\n\n\n### [Spawn a worker](../docs/reference/slack.md#create-a-new-slackbotworker)\n\nIt is possible to spawn bot workers bound to a specific team by passing the team ID as the primary parameter to `controller.spawn()`:\n\n```javascript\nlet bot = await controller.spawn(SLACK_TEAM_ID);\n```\n\n### Start or resume conversations with people\n\nUse these method to initiate a conversation with a user, or in a specific channel or thread. After calling these methods, any further actions carried out by the bot worker will happen in that context.\n\nThis can be used to create or resume conversations with users that are not in direct response to an incoming message, like those sent on a schedule or in response to external events.\n\n* [bot.startPrivateConversation()](../docs/reference/slack.md#startprivateconversation)\n* [bot.startConversationInChannel()](../docs/reference/slack.md#startconversationinchannel)\n* [bot.startConversationInThread()](../docs/reference/slack.md#startconversationinthread)\n\n### Slash Commands\n\nSlash commands are special commands triggered by typing a \"/\" then a command. They are configured inside Slack's API portal.\n\n[Read Slack's documentation for Slash commands here &rarr;](https://api.slack.com/slash-commands)\n\nWhen a Botkit application receives a request from a slash command, it will emit a `slash_command` event that can be handled using `controller.on()`.  Several additional reply methods have been provided to handle slash commands.\n\n* [bot.replyPublic()](../docs/reference/slack.md#replypublic)\n* [bot.replyPrivate()](../docs/reference/slack.md#replyprivate)\n\n```javascript\ncontroller.on('slash_command', async(bot, message) => { \n\n    // the /<command> part\n    let command = message.command;\n    // the /command <parameters> part\n    let parameter = message.text;\n\n    await bot.replyPublic(message, 'My response to your command is: ...');\n\n});\n```\n\nNote that if you would prefer to send a response to the Slash command via the synchronous http response back to Slack, you can achieve this by using [bot.httpBody()](../docs/reference/core.md#httpbody).\n\n```javascript\ncontroller.on('slash_command', async(bot, message) => {\n    bot.httpBody({text:'You can send an immediate response using bot.httpBody()'});\n});\n```\n\n### Work with threads\n\nMessages in Slack may now exist as part of a thread, separate from the messages included in the main channel. Threads can be used to create new and interesting interactions for bots.\n\nBotkit's default behavior is for replies to be sent in-context. That is, if a bot replies to a message in a main channel, the reply will be added to the main channel. If a bot replies to a message in a thread, the reply will be added to the thread. This behavior can be changed by using one of the following specialized functions:\n\n* [bot.replyInThread()](../docs/reference/slack.md#replyinthread)\n* [bot.startConversationInThread()](../docs/reference/slack.md#startconversationinthread)\n\n### Ephemeral Messages\n\nMessages can be sent to a user \"ephemerally\" which will only show to them, and no one else. [Learn more about ephemeral messages at the Slack API Documentation.](https://api.slack.com/methods/chat.postEphemeral)\n\n* [bot.replyEphemeral()](../docs/reference/slack.md#replyephemeral)\n\n### Interactive messages\n\nSlack applications can use \"interactive messages\" to include buttons, menus and other interactive elements to improve the user's experience. [See here for how to attach cards and blocks.](#use-attachments-blocks-and-other-rich-message-features)\n\nIf your interactive message contains a button, when the user clicks the button in Slack, Botkit triggers an event based on the message type.\n\nWhen an event is received, your bot can either reply normally, or use the special `bot.replyInteractive` function which will result in the original message in Slack being _replaced_ by the reply. Using `replyInteractive`, bots can present dynamic interfaces inside a single message.\n\nTo receive callbacks, register a callback url as part of applications configuration. Botkit's built in support for the Slack Button system supports interactive message callbacks at same url as other events (`/api/messages` by default). \n\n* [bot.replyInteractive()](../docs/reference/slack.md#replyinteractive)\n\n### Work with Slack Dialogs\n\n[Dialogs](https://api.slack.com/dialogs) allow bots to present multi-field pop-up forms in response to a button click or other interactive message interaction.\nBotkit provides helper functions and special events to make using dialogs in your app possible.\n\nDialogs can be created in response to `interactive_message` or `slash_command` events.\nBotkit provides a specialized reply function, `bot.replyWithDialog()` and a object builder class,\n`SlackDialog` that should be used to create and send the dialog.\n\n* [bot.replyWithDialog()](../docs/reference/slack.md#replywithdialog)\n* [bot.dialogError()](../docs/reference/slack.md#dialogerror)\n* [SlackDialog](../docs/reference/slack.md#slackdialog)\n\n### Update and remove messages\n\nSlack supports updating and deleting messages. Do so with the following convenience methods:\n\n* [bot.updateMessage()](../docs/reference/slack.md#updatemessage)\n* [bot.deleteMessage()](../docs/reference/slack.md#deletemessage)\n\n## Community & Support\n\nJoin our thriving community of Botkit developers and bot enthusiasts at large.\nOver 10,000 members strong, [our open Slack group](https://community.botkit.ai) is\n_the place_ for people interested in the art and science of making bots.\nCome to ask questions, share your progress, and commune with your peers!\n\nYou can also find help from members of the Botkit team [in our dedicated Cisco Spark room](https://eurl.io/#SyNZuomKx)!\n\n## About Botkit\n\nBotkit is a part of the [Microsoft Bot Framework](https://dev.botframework.com).\n\nWant to contribute? [Read the contributor guide](https://github.com/howdyai/botkit/blob/master/CONTRIBUTING.md)\n\nBotkit is released under the [MIT Open Source license](https://github.com/howdyai/botkit/blob/master/LICENSE.md)\n"
  },
  {
    "path": "packages/botbuilder-adapter-slack/src/botworker.ts",
    "content": "/**\n * @module botbuilder-adapter-slack\n */\n/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { Botkit, BotkitMessage, BotWorker } from 'botkit';\nimport { WebClient, Dialog } from '@slack/web-api';\nimport * as request from 'request';\n\n/**\n * This is a specialized version of [Botkit's core BotWorker class](core.md#BotWorker) that includes additional methods for interacting with Slack.\n * It includes all functionality from the base class, as well as the extension methods below.\n *\n * When using the SlackAdapter with Botkit, all `bot` objects passed to handler functions will include these extensions.\n */\nexport class SlackBotWorker extends BotWorker {\n    /**\n     * A copy of hte Slack WebClient giving, giving access to all of Slack's APIs via `let res = await bot.api.object.method(params);`\n     */\n    public api: WebClient;\n\n    /**\n     * Reserved for use internally by Botkit's `controller.spawn()`, this class is used to create a BotWorker instance that can send messages, replies, and make other API calls.\n     *\n     * It is possible to spawn a bot instance by passing in the Slack workspace ID of a team that has installed the app.\n     * Use this in concert with [startPrivateConversation()](#startPrivateConversation) and [changeContext()](core.md#changecontext) to start conversations\n     * or send proactive alerts to users on a schedule or in response to external events.\n     *\n     *\n     * ```javascript\n     * // spawn a bot for a given team.\n     * let bot = await controller.spawn('T0123456');\n     *\n     * // start a 1:1 with a specific user\n     * await bot.startPrivateConversation('U0123456');\n     *\n     * // send a message\n     * await bot.say('Hi user');\n     * ```\n     *\n     * @param botkit The Botkit controller object responsible for spawning this bot worker\n     * @param config Normally, a DialogContext object.  Can also be the id of a team.\n     */\n    public constructor(botkit: Botkit, config: any) {\n        // allow a teamid to be passed in\n        if (typeof config === 'string') {\n            const team_id = config;\n            config = {\n                // an activity is required to spawn the bot via the api\n                activity: {\n                    conversation: {\n                        team: team_id\n                    }\n                },\n                // a reference is used to spawn an api instance inside the adapter...\n                reference: {\n                    conversation: {\n                        team: team_id\n                    }\n                }\n            };\n        }\n\n        super(botkit, config);\n    }\n\n    /**\n     * Switch a bot's context to a 1:1 private message channel with a specific user.\n     * After calling this method, messages sent with `bot.say` and any dialogs started with `bot.beginDialog` will occur in this new context.\n     *\n     * ```javascript\n     * controller.hears('dm me', 'message', async(bot, message) => {\n     *\n     *      // switch to a 1:1 conversation in a DM\n     *      await bot.startPrivateConversation(message.user);\n     *\n     *      // say hello\n     *      await bot.say('We are in private now...');\n     *      await bot.beginDialog(MY_PRIVATE_DIALOG);\n     *\n     * });\n     * ```\n     *\n     * Also useful when sending pro-active messages such as those sent on a schedule or in response to external events:\n     * ```javascript\n     * // Spawn a worker with a Slack team id.\n     * let bot = await controller.spawn(SLACK_TEAM_ID);\n     *\n     * // Set the context for the bot's next action...\n     * await bot.startPrivateConversation(SLACK_ADMIN_USER);\n     *\n     * // Begin a dialog in the 1:1 context\n     * await bot.beginDialog(ALERT_DIALOG);\n     * ```\n     *\n     * @param userId A Slack user id, like one found in `message.user` or in a `<@mention>`\n     */\n    public async startPrivateConversation(userId: string): Promise<any> {\n        // create the new IM channel\n        const channel: any = await this.api.conversations.open({ users: userId });\n\n        if (channel.ok === true) {\n            // now, switch contexts\n            return this.changeContext({\n                conversation: {\n                    id: channel.channel.id,\n                    // @ts-ignore this field is required for slack\n                    team: this.getConfig('activity').conversation.team\n                },\n                user: { id: userId, name: null },\n                channelId: 'slack'\n            });\n        } else {\n            console.error(channel);\n            throw new Error('Error creating IM channel');\n        }\n    }\n\n    /**\n     * Switch a bot's context into a different channel.\n     * After calling this method, messages sent with `bot.say` and any dialogs started with `bot.beginDialog` will occur in this new context.\n     *\n     * ```javascript\n     * controller.hears('dm me', 'message', async(bot, message) => {\n     *\n     *      // switch to the channel specified in SLACK_CHANNEL_ID\n     *      // if just using bot.say and not starting a dialog, can use a fake value for user id.\n     *      await bot.startConversationInChannel(SLACK_CHANNEL_ID, message.user);\n     *\n     *      // say hello\n     *      await bot.say('Shall we discuss this matter over here?');\n     *      // ... continue...\n     *      await bot.beginDialog(ANOTHER_DIALOG);\n     *\n     * });\n     * ```\n     * @param channelId A Slack channel id, like one found in `message.channel`\n     * @param userId A Slack user id, like one found in `message.user` or in a `<@mention>`\n     */\n    public async startConversationInChannel(channelId: string, userId: string): Promise<any> {\n        return this.changeContext({\n            conversation: {\n                id: channelId,\n                // @ts-ignore this field is required for slack\n                team: this.getConfig('activity').conversation.team\n            },\n            user: { id: userId, name: null },\n            channelId: 'slack'\n        });\n    }\n\n    /**\n     * Switch a bot's context into a specific sub-thread within a channel.\n     * After calling this method, messages sent with `bot.say` and any dialogs started with `bot.beginDialog` will occur in this new context.\n     *\n     * ```javascript\n     * controller.hears('in a thread', 'message', async(bot, message) => {\n     *\n     *      // branch from the main channel into a side thread associated with this message\n     *      await bot.startConversationInThread(message.channel, message.user, message.ts);\n     *\n     *      // say hello\n     *      await bot.say(`Let's handle this offline...`);\n     *      // ... continue...\n     *      await bot.beginDialog(OFFLINE_DIALOG);\n     *\n     * });\n     * ```\n     * @param channelId A Slack channel id, like one found in `message.channel`\n     * @param userId A Slack user id, like one found in `message.user` or in a `<@mention>`\n     * @param thread_ts A thread_ts value found in the `message.thread_ts` or `message.ts` field.\n     */\n    public async startConversationInThread(channelId: string, userId: string, thread_ts: string): Promise<any> {\n        return this.changeContext({\n            conversation: {\n                id: channelId,\n                // @ts-ignore this field is required for slack\n                thread_ts: thread_ts,\n                team: this.getConfig('activity').conversation.team\n            },\n            user: { id: userId, name: null },\n            channelId: 'slack'\n        });\n    }\n\n    /**\n     * Like bot.reply, but as a threaded response to the incoming message rather than a new message in the main channel.\n     * @param src an incoming message object\n     * @param resp an outgoing message object (or part of one or just reply text)\n     */\n    public async replyInThread(src: any, resp: any): Promise<any> {\n        // make sure the  thread_ts setting is set\n        // this will be included in the conversation reference\n        src.incoming_message.conversation.thread_ts = src.incoming_message.channelData.thread_ts ? src.incoming_message.channelData.thread_ts : src.incoming_message.channelData.ts;\n        return this.reply(src, resp);\n    }\n\n    /**\n     * Like bot.reply, but sent as an \"ephemeral\" message meaning only the recipient can see it.\n     * Uses [chat.postEphemeral](https://api.slack.com/methods/chat.postEphemeral)\n     * @param src an incoming message object\n     * @param resp an outgoing message object (or part of one or just reply text)\n     */\n    public async replyEphemeral(src: any, resp: any): Promise<any> {\n        // make rure resp is in an object format.\n        resp = this.ensureMessageFormat(resp);\n\n        // make sure ephemeral is set\n        // fields set in channelData will end up in the final message to slack\n        resp.channelData = {\n            ...resp.channelData,\n            ephemeral: true\n        };\n\n        return this.reply(src, resp);\n    }\n\n    /**\n     * Like bot.reply, but used to send an immediate public reply to a /slash command.\n     * The message in `resp` will be displayed to everyone in the channel.\n     * @param src an incoming message object of type `slash_command`\n     * @param resp an outgoing message object (or part of one or just reply text)\n     */\n    public async replyPublic(src: any, resp: any): Promise<any> {\n        const msg = this.ensureMessageFormat(resp);\n        msg.channelData.response_type = 'in_channel';\n\n        return this.replyInteractive(src, msg);\n    };\n\n    /**\n     * Like bot.reply, but used to send an immediate private reply to a /slash command.\n     * The message in `resp` will be displayed only to the person who executed the slash command.\n     * @param src an incoming message object of type `slash_command`\n     * @param resp an outgoing message object (or part of one or just reply text)\n     */\n    public async replyPrivate(src: any, resp: any): Promise<any> {\n        const msg = this.ensureMessageFormat(resp);\n\n        msg.channelData.response_type = 'ephemeral';\n        msg.channelData.to = src.user;\n\n        return this.replyInteractive(src, msg);\n    };\n\n    /**\n     * Like bot.reply, but used to respond to an `interactive_message` event and cause the original message to be replaced with a new one.\n     * @param src an incoming message object of type `interactive_message`\n     * @param resp a new or modified message that will replace the original one\n     */\n    public async replyInteractive(src: any, resp: any): Promise<any> {\n        if (!src.incoming_message.channelData.response_url) {\n            throw Error('No response_url found in incoming message');\n        } else {\n            let msg = this.ensureMessageFormat(resp);\n            // @ts-ignore\n            msg.conversation = {\n                id: src.channel\n            };\n            msg.channelData.to = src.user;\n\n            // if source message is in a thread, reply should also be in the thread\n            if (src.incoming_message.channelData.thread_ts) {\n                // @ts-ignore\n                msg.conversation.thread_ts = src.incoming_message.channelData.thread_ts;\n            }\n\n            msg = this.getConfig('adapter').activityToSlack(msg);\n\n            const requestOptions = {\n                uri: src.incoming_message.channelData.response_url,\n                method: 'POST',\n                json: msg\n            };\n\n            return new Promise(function(resolve, reject) {\n                request(requestOptions, function(err, res, body) {\n                    if (err) {\n                        reject(err);\n                    } else {\n                        resolve(body);\n                    }\n                });\n            });\n        }\n    };\n\n    /**\n     * Return 1 or more error to a `dialog_submission` event that will be displayed as form validation errors.\n     * Each error must be mapped to the name of an input in the dialog.\n     * @param errors 1 or more objects in form {name: string, error: string}\n     */\n    public dialogError(errors: {name: string; error: string} | { name: string; error: string }[]): void {\n        if (!errors) {\n            errors = [];\n        }\n\n        if (!Array.isArray(errors)) {\n            errors = [errors];\n        }\n\n        this.httpBody(JSON.stringify({ errors }));\n    };\n\n    /**\n     * Reply to a button click with a request to open a dialog.\n     * @param src An incoming `interactive_callback` event containing a `trigger_id` field\n     * @param dialog_obj A dialog, as created using [SlackDialog](#SlackDialog) or [authored to this spec](https://api.slack.com/dialogs).\n     */\n    public async replyWithDialog(src, dialog_obj: Dialog): Promise<any> {\n        const msg = {\n            trigger_id: src.trigger_id,\n            dialog: dialog_obj\n        };\n\n        return this.api.dialog.open(msg);\n    };\n\n    /**\n     * Update an existing message with new content.\n     *\n     * ```javascript\n     * // send a reply, capture the results\n     * let sent = await bot.reply(message,'this is my original reply...');\n     *\n     * // update the sent message using the sent.id field\n     * await bot.updateMessage({\n     *      text: 'this is an update!',\n     *      ...sent\n     * })\n     * ```\n     *\n     * @param update An object in the form `{id: <id of message to update>, conversation: { id: <channel> }, text: <new text>, card: <array of card objects>}`\n     */\n    public async updateMessage(update: Partial<BotkitMessage>): Promise<any> {\n        return this.getConfig('adapter').updateActivity(\n            this.getConfig('context'),\n            update\n        );\n    }\n\n    /**\n     * Delete an existing message.\n     *\n     * ```javascript\n     * // send a reply, capture the results\n     * let sent = await bot.reply(message,'this is my original reply...');\n     *\n     * // delete the sent message using the sent.id field\n     * await bot.deleteMessage(sent);\n     * ```\n     *\n     * @param update An object in the form of `{id: <id of message to delete>, conversation: { id: <channel of message> }}`\n     */\n    public async deleteMessage(update: Partial<BotkitMessage>): Promise<any> {\n        return this.getConfig('adapter').deleteActivity(\n            this.getConfig('context'),\n            {\n                activityId: update.id,\n                conversation: update.conversation\n            }\n        );\n    }\n}\n"
  },
  {
    "path": "packages/botbuilder-adapter-slack/src/index.ts",
    "content": "/**\n * @module botbuilder-adapter-slack\n */\n/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport * from './slack_adapter';\nexport * from './slack_dialog';\nexport * from './messagetype_middleware';\nexport * from './slackevent_middleware';\nexport * from './botworker';\n"
  },
  {
    "path": "packages/botbuilder-adapter-slack/src/messagetype_middleware.ts",
    "content": "/**\n * @module botbuilder-adapter-slack\n */\n/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ActivityTypes, TurnContext, MiddlewareSet } from 'botbuilder';\nimport { SlackAdapter } from './slack_adapter';\n\n/**\n * A middleware for Botkit developers using the BotBuilder SlackAdapter class.\n * This middleware causes Botkit to emit more specialized events for the different types of message that Slack might send.\n * Responsible for classifying messages:\n *\n *      * `direct_message` events are messages received through 1:1 direct messages with the bot\n *      * `direct_mention` events are messages that start with a mention of the bot, i.e \"@mybot hello there\"\n *      * `mention` events are messages that include a mention of the bot, but not at the start, i.e \"hello there @mybot\"\n *\n * In addition, messages from bots and changing them to `bot_message` events. All other types of message encountered remain `message` events.\n *\n * To use this, bind it to the adapter before creating the Botkit controller:\n * ```javascript\n * const adapter = new SlackAdapter(options);\n * adapter.use(new SlackMessageTypeMiddleware());\n * const controller = new Botkit({\n *      adapter: adapter,\n *      // ...\n * });\n * ```\n */\nexport class SlackMessageTypeMiddleware extends MiddlewareSet {\n    /**\n     * Not for direct use - implements the MiddlewareSet's required onTurn function used to process the event\n     * @param context\n     * @param next\n     */\n    public async onTurn(context: TurnContext, next: () => Promise<any>): Promise<void> {\n        if (context.activity.type === 'message' && context.activity.channelData) {\n            const adapter = context.adapter as SlackAdapter;\n\n            const bot_user_id = await adapter.getBotUserByTeam(context.activity);\n            const mentionSyntax = '<@' + bot_user_id + '(\\\\|.*?)?>';\n            const mention = new RegExp(mentionSyntax, 'i');\n            const direct_mention = new RegExp('^' + mentionSyntax, 'i');\n\n            // is this a DM, a mention, or just ambient messages passing through?\n            if (context.activity.channelData.type === 'block_actions') {\n                context.activity.channelData.botkitEventType = 'block_actions';\n            } else if (context.activity.channelData.type === 'interactive_message') {\n                context.activity.channelData.botkitEventType = 'interactive_message';\n            } else if (context.activity.channelData.channel_type && context.activity.channelData.channel_type === 'im') {\n                context.activity.channelData.botkitEventType = 'direct_message';\n\n                // strip any potential leading @mention\n                context.activity.text = context.activity.text.replace(direct_mention, '')\n                    .replace(/^\\s+/, '').replace(/^:\\s+/, '').replace(/^\\s+/, '');\n            } else if (bot_user_id && context.activity.text && context.activity.text.match(direct_mention)) {\n                context.activity.channelData.botkitEventType = 'direct_mention';\n\n                // strip the @mention\n                context.activity.text = context.activity.text.replace(direct_mention, '')\n                    .replace(/^\\s+/, '').replace(/^:\\s+/, '').replace(/^\\s+/, '');\n            } else if (bot_user_id && context.activity.text && context.activity.text.match(mention)) {\n                context.activity.channelData.botkitEventType = 'mention';\n            } else {\n                // this is an \"ambient\" message\n            }\n\n            // if this is a message from a bot, we probably want to ignore it.\n            // switch the botkit event type to bot_message\n            // and the activity type to Event <-- will stop it from being included in dialogs\n            // NOTE: This catches any message from any bot, including this bot.\n            // Note also, bot_id here is not the same as bot_user_id so we can't (yet) identify messages originating from this bot without doing an additional API call.\n            if (context.activity.channelData && context.activity.channelData.bot_id) {\n                context.activity.channelData.botkitEventType = 'bot_message';\n                context.activity.type = ActivityTypes.Event;\n            }\n        }\n        await next();\n    }\n}\n"
  },
  {
    "path": "packages/botbuilder-adapter-slack/src/slack_adapter.ts",
    "content": "/**\n * @module botbuilder-adapter-slack\n */\n/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { Activity, ActivityTypes, BotAdapter, TurnContext, ConversationReference, ResourceResponse } from 'botbuilder';\nimport { WebClient, WebAPICallResult } from '@slack/web-api';\nimport { SlackBotWorker } from './botworker';\nimport * as crypto from 'crypto';\nimport * as Debug from 'debug';\nconst debug = Debug('botkit:slack');\n\n/**\n * Connect [Botkit](https://www.npmjs.com/package/botkit) or [BotBuilder](https://www.npmjs.com/package/botbuilder) to Slack.\n */\nexport class SlackAdapter extends BotAdapter {\n    private options: SlackAdapterOptions;\n    private slack: WebClient;\n    private identity: {\n        user_id: string;\n    };\n\n    /**\n     * Name used by Botkit plugin loader\n     * @ignore\n     */\n    public name = 'Slack Adapter';\n\n    /**\n     * Object containing one or more Botkit middlewares to bind automatically.\n     * @ignore\n     */\n    public middlewares;\n\n    /**\n     * A customized BotWorker object that exposes additional utility methods.\n     * @ignore\n     */\n    public botkit_worker = SlackBotWorker;\n\n    /**\n     * Create a Slack adapter.\n     *\n     * The SlackAdapter can be used in 2 modes:\n     *      * As an \"[internal integration](https://api.slack.com/internal-integrations) connected to a single Slack workspace\n     *      * As a \"[Slack app](https://api.slack.com/slack-apps) that uses oauth to connect to multiple workspaces and can be submitted to the Slack app.\n     *\n     * [Read here for more information about all the ways to configure the SlackAdapter &rarr;](../../botbuilder-adapter-slack/readme.md).\n     *\n     * Use with Botkit:\n     *```javascript\n     * const adapter = new SlackAdapter({\n     *      clientSigningSecret: process.env.CLIENT_SIGNING_SECRET,\n     *      botToken: process.env.BOT_TOKEN\n     * });\n     * const controller = new Botkit({\n     *      adapter: adapter,\n     *      // ... other configuration options\n     * });\n     * ```\n     *\n     * Use with BotBuilder:\n     *```javascript\n     * const adapter = new SlackAdapter({\n     *      clientSigningSecret: process.env.CLIENT_SIGNING_SECRET,\n     *      botToken: process.env.BOT_TOKEN\n     * });\n     * // set up restify...\n     * const server = restify.createServer();\n     * server.use(restify.plugins.bodyParser());\n     * server.post('/api/messages', (req, res) => {\n     *      adapter.processActivity(req, res, async(context) => {\n     *          // do your bot logic here!\n     *      });\n     * });\n     * ```\n     *\n     * Use in \"Slack app\" multi-team mode:\n     * ```javascript\n     * const adapter = new SlackAdapter({\n     *     clientSigningSecret: process.env.CLIENT_SIGNING_SECRET,\n     *     clientId: process.env.CLIENT_ID, // oauth client id\n     *     clientSecret: process.env.CLIENT_SECRET, // oauth client secret\n     *     scopes: ['bot'], // oauth scopes requested\n     *     oauthVersion: 'v1',\n     *     redirectUri: process.env.REDIRECT_URI, // url to redirect post login defaults to `https://<mydomain>/install/auth`\n     *     getTokenForTeam: async(team_id) => Promise<string>, // function that returns a token based on team id\n     *     getBotUserByTeam: async(team_id) => Promise<string>, // function that returns a bot's user id based on team id\n     * });\n     * ```\n     *\n     * @param options An object containing API credentials, a webhook verification token and other options\n     */\n    public constructor(options: SlackAdapterOptions) {\n        super();\n\n        this.options = options;\n\n        /*\n        * Check for security options. If these are not set, malicious actors can\n        * spoof messages from Slack.\n        * These will be required in upcoming versions of Botkit.\n        */\n        if (!this.options.verificationToken && !this.options.clientSigningSecret) {\n            const warning = [\n                '',\n                '****************************************************************************************',\n                '* WARNING: Your bot is operating without recommended security mechanisms in place.     *',\n                '* Initialize your adapter with a clientSigningSecret parameter to enable               *',\n                '* verification that all incoming webhooks originate with Slack:                        *',\n                '*                                                                                      *',\n                '* var adapter = new SlackAdapter({clientSigningSecret: <my secret from slack>});       *',\n                '*                                                                                      *',\n                '****************************************************************************************',\n                '>> Slack docs: https://api.slack.com/docs/verifying-requests-from-slack',\n                ''\n            ];\n            console.warn(warning.join('\\n'));\n            if (!this.options.enable_incomplete) {\n                throw new Error('Required: include a verificationToken or clientSigningSecret to verify incoming Events API webhooks');\n            }\n        }\n\n        if (this.options.botToken) {\n            this.slack = new WebClient(this.options.botToken);\n            this.slack.auth.test().then((raw_identity) => {\n                const identity = raw_identity as AuthTestResult;\n                debug('** Slack adapter running in single team mode.');\n                debug('** My Slack identity: ', identity.user, 'on team', identity.team);\n                this.identity = { user_id: identity.user_id };\n            }).catch((err) => {\n                // This is a fatal error! Invalid credentials have been provided and the bot can't start.\n                console.error(err);\n                process.exit(1);\n            });\n        } else if (!this.options.getTokenForTeam || !this.options.getBotUserByTeam) {\n            // This is a fatal error. No way to get a token to interact with the Slack API.\n            console.error('Missing Slack API credentials! Provide either a botToken or a getTokenForTeam() and getBotUserByTeam function as part of the SlackAdapter options.');\n            if (!this.options.enable_incomplete) {\n                throw new Error('Incomplete Slack configuration');\n            }\n        } else if (!this.options.clientId || !this.options.clientSecret || !this.options.scopes || !this.options.redirectUri) {\n            // This is a fatal error. Need info to connet to Slack via oauth\n            console.error('Missing Slack API credentials! Provide clientId, clientSecret, scopes and redirectUri as part of the SlackAdapter options.');\n            if (!this.options.enable_incomplete) {\n                throw new Error('Incomplete Slack configuration');\n            }\n        } else {\n            debug('** Slack adapter running in multi-team mode.');\n        }\n\n        if (!this.options.oauthVersion) {\n            this.options.oauthVersion = 'v1';\n        }\n        this.options.oauthVersion = this.options.oauthVersion.toLowerCase();\n\n        if (this.options.enable_incomplete) {\n            const warning = [\n                '',\n                '****************************************************************************************',\n                '* WARNING: Your adapter may be running with an incomplete/unsafe configuration.        *',\n                '* - Ensure all required configuration options are present                              *',\n                '* - Disable the \"enable_incomplete\" option!                                            *',\n                '****************************************************************************************',\n                ''\n            ];\n            console.warn(warning.join('\\n'));\n        }\n\n        this.middlewares = {\n            spawn: [\n                async (bot, next): Promise<void> => {\n                    // make the Slack API available to all bot instances.\n                    bot.api = await this.getAPI(bot.getConfig('activity')).catch((err) => {\n                        debug('An error occurred while trying to get API creds for team', err);\n                        return next(new Error('Could not spawn a Slack API instance'));\n                    });\n\n                    next();\n                }\n            ]\n        };\n    }\n\n    /**\n     * Get a Slack API client with the correct credentials based on the team identified in the incoming activity.\n     * This is used by many internal functions to get access to the Slack API, and is exposed as `bot.api` on any bot worker instances.\n     * @param activity An incoming message activity\n     */\n    public async getAPI(activity: Partial<Activity>): Promise<WebClient> {\n        // use activity.channelData.team.id (the slack team id) and get the appropriate token using getTokenForTeam\n        if (this.slack) {\n            return this.slack;\n        } else {\n            // @ts-ignore\n            if (activity.conversation.team) {\n                // @ts-ignore\n                const token = await this.options.getTokenForTeam(activity.conversation.team);\n                if (!token) {\n                    throw new Error('Missing credentials for team.');\n                }\n                return new WebClient(token);\n            } else {\n                // No API can be created, this is\n                debug('Unable to create API based on activity: ', activity);\n            }\n        }\n    }\n\n    /**\n     * Get the bot user id associated with the team on which an incoming activity originated. This is used internally by the SlackMessageTypeMiddleware to identify direct_mention and mention events.\n     * In single-team mode, this will pull the information from the Slack API at launch.\n     * In multi-team mode, this will use the `getBotUserByTeam` method passed to the constructor to pull the information from a developer-defined source.\n     * @param activity An incoming message activity\n     */\n    public async getBotUserByTeam(activity: Partial<Activity>): Promise<string> {\n        if (this.identity) {\n            return this.identity.user_id;\n        } else {\n            // @ts-ignore\n            if (activity.conversation.team) {\n                // @ts-ignore\n                const user_id = await this.options.getBotUserByTeam(activity.conversation.team);\n                if (!user_id) {\n                    throw new Error('Missing credentials for team.');\n                }\n                return user_id;\n            } else {\n                debug('Could not find bot user id based on activity: ', activity);\n            }\n        }\n    }\n\n    /**\n     * Get the oauth link for this bot, based on the clientId and scopes passed in to the constructor.\n     *\n     * An example using Botkit's internal webserver to configure the /install route:\n     *\n     * ```javascript\n     * controller.webserver.get('/install', (req, res) => {\n     *  res.redirect(controller.adapter.getInstallLink());\n     * });\n     * ```\n     *\n     * @returns A url pointing to the first step in Slack's oauth flow.\n     */\n    public getInstallLink(): string {\n        let redirect = '';\n        if (this.options.clientId && this.options.scopes) {\n            if (this.options.oauthVersion === 'v2') {\n                redirect = 'https://slack.com/oauth/v2/authorize?client_id=' + this.options.clientId + '&scope=' + this.options.scopes.join(',');\n            } else {\n                redirect = 'https://slack.com/oauth/authorize?client_id=' + this.options.clientId + '&scope=' + this.options.scopes.join(',');\n            }\n            if (this.options.redirectUri) {\n                redirect += '&redirect_uri=' + encodeURIComponent(this.options.redirectUri);\n            }\n\n            return redirect;\n        } else {\n            throw new Error('getInstallLink() cannot be called without clientId and scopes in adapter options');\n        }\n    }\n\n    /**\n     * Validates an oauth v2 code sent by Slack during the install process.\n     *\n     * An example using Botkit's internal webserver to configure the /install/auth route:\n     *\n     * ```javascript\n     * controller.webserver.get('/install/auth', async (req, res) => {\n     *      try {\n     *          const results = await controller.adapter.validateOauthCode(req.query.code);\n     *          // make sure to capture the token and bot user id by team id...\n     *          const team_id = results.team.id;\n     *          const token = results.access_token;\n     *          const bot_user = results.bot_user_id;\n     *          // store these values in a way they'll be retrievable with getBotUserByTeam and getTokenForTeam\n     *      } catch (err) {\n     *           console.error('OAUTH ERROR:', err);\n     *           res.status(401);\n     *           res.send(err.message);\n     *      }\n     * });\n     * ```\n     * @param code the value found in `req.query.code` as part of Slack's response to the oauth flow.\n     */\n    public async validateOauthCode(code: string): Promise<any> {\n        const slack = new WebClient();\n        const details = {\n            code: code,\n            client_id: this.options.clientId,\n            client_secret: this.options.clientSecret,\n            redirect_uri: this.options.redirectUri\n        };\n        let results: any = {};\n        if (this.options.oauthVersion === 'v2') {\n            results = await slack.oauth.v2.access(details);\n        } else {\n            results = await slack.oauth.access(details);\n        }\n        if (results.ok) {\n            return results;\n        } else {\n            throw new Error(results.error);\n        }\n    }\n\n    /**\n     * Formats a BotBuilder activity into an outgoing Slack message.\n     * @param activity A BotBuilder Activity object\n     * @returns a Slack message object with {text, attachments, channel, thread_ts} as well as any fields found in activity.channelData\n     */\n    public activityToSlack(activity: Partial<Activity>): any {\n        const channelId = activity.conversation.id;\n        // @ts-ignore ignore this non-standard field\n        const thread_ts = activity.conversation.thread_ts;\n\n        const message: any = {\n            ts: activity.id,\n            text: activity.text,\n            attachments: activity.attachments,\n\n            channel: channelId,\n            thread_ts: thread_ts\n        };\n\n        // if channelData is specified, overwrite any fields in message object\n        if (activity.channelData) {\n            Object.keys(activity.channelData).forEach(function(key) {\n                message[key] = activity.channelData[key];\n            });\n        }\n\n        // should this message be sent as an ephemeral message\n        if (message.ephemeral) {\n            message.user = activity.recipient.id;\n        }\n\n        if (message.icon_url || message.icon_emoji || message.username) {\n            message.as_user = false;\n        }\n\n        // as_user flag is deprecated on v2\n        if (message.as_user === false && this.options.oauthVersion === 'v2') {\n            delete message.as_user;\n        }\n\n        return message;\n    }\n\n    /**\n     * Standard BotBuilder adapter method to send a message from the bot to the messaging API.\n     * [BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#sendactivities).\n     * @param context A TurnContext representing the current incoming message and environment.\n     * @param activities An array of outgoing activities to be sent back to the messaging API.\n     */\n    public async sendActivities(context: TurnContext, activities: Partial<Activity>[]): Promise<ResourceResponse[]> {\n        const responses = [];\n        for (let a = 0; a < activities.length; a++) {\n            const activity = activities[a];\n            if (activity.type === ActivityTypes.Message) {\n                const message = this.activityToSlack(activity as Activity);\n\n                try {\n                    const slack = await this.getAPI(context.activity);\n                    let result = null;\n\n                    if (message.ephemeral) {\n                        debug('chat.postEphemeral:', message);\n                        result = await slack.chat.postEphemeral(message) as ChatPostMessageResult;\n                    } else {\n                        debug('chat.postMessage:', message);\n                        result = await slack.chat.postMessage(message) as ChatPostMessageResult;\n                    }\n                    if (result.ok === true) {\n                        responses.push({\n                            id: result.ts,\n                            activityId: result.ts,\n                            conversation: { id: result.channel }\n                        });\n                    } else {\n                        console.error('Error sending activity to API:', result);\n                    }\n                } catch (err) {\n                    console.error('Error sending activity to API:', err);\n                }\n            } else {\n                // If there are ever any non-message type events that need to be sent, do it here.\n                debug('Unknown message type encountered in sendActivities: ', activity.type);\n            }\n        }\n\n        return responses;\n    }\n\n    /**\n     * Standard BotBuilder adapter method to update a previous message with new content.\n     * [BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#updateactivity).\n     * @param context A TurnContext representing the current incoming message and environment.\n     * @param activity The updated activity in the form `{id: <id of activity to update>, ...}`\n     */\n    public async updateActivity(context: TurnContext, activity: Partial<Activity>): Promise<void> {\n        if (activity.id && activity.conversation) {\n            try {\n                const message = this.activityToSlack(activity as Activity);\n                const slack = await this.getAPI(activity);\n                const results = await slack.chat.update(message);\n                if (!results.ok) {\n                    console.error('Error updating activity on Slack:', results);\n                }\n            } catch (err) {\n                console.error('Error updating activity on Slack:', err);\n            }\n        } else {\n            throw new Error('Cannot update activity: activity is missing id');\n        }\n    }\n\n    /**\n     * Standard BotBuilder adapter method to delete a previous message.\n     * [BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#deleteactivity).\n     * @param context A TurnContext representing the current incoming message and environment.\n     * @param reference An object in the form `{activityId: <id of message to delete>, conversation: { id: <id of slack channel>}}`\n     */\n    public async deleteActivity(context: TurnContext, reference: Partial<ConversationReference>): Promise<void> {\n        if (reference.activityId && reference.conversation) {\n            try {\n                const slack = await this.getAPI(context.activity);\n                const results = await slack.chat.delete({ ts: reference.activityId, channel: reference.conversation.id });\n                if (!results.ok) {\n                    console.error('Error deleting activity:', results);\n                }\n            } catch (err) {\n                console.error('Error deleting activity', err);\n                throw err;\n            }\n        } else {\n            throw new Error('Cannot delete activity: reference is missing activityId');\n        }\n    }\n\n    /**\n     * Standard BotBuilder adapter method for continuing an existing conversation based on a conversation reference.\n     * [BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#continueconversation)\n     * @param reference A conversation reference to be applied to future messages.\n     * @param logic A bot logic function that will perform continuing action in the form `async(context) => { ... }`\n     */\n    public async continueConversation(reference: Partial<ConversationReference>, logic: (context: TurnContext) => Promise<void>): Promise<void> {\n        const request = TurnContext.applyConversationReference(\n            { type: 'event', name: 'continueConversation' },\n            reference,\n            true\n        );\n        const context = new TurnContext(this, request);\n\n        return this.runMiddleware(context, logic);\n    }\n\n    /**\n     * Verify the signature of an incoming webhook request as originating from Slack.\n     * @param req A request object from Restify or Express\n     * @param res A response object from Restify or Express\n     * @returns If signature is valid, returns true. Otherwise, sends a 401 error status via http response and then returns false.\n     */\n    private async verifySignature(req, res): Promise<boolean> {\n        // is this an verified request from slack?\n        if (this.options.clientSigningSecret && req.rawBody) {\n            const timestamp = req.header('X-Slack-Request-Timestamp');\n            const body = req.rawBody;\n\n            const signature = [\n                'v0',\n                timestamp, // slack request timestamp\n                body // request body\n            ];\n            const basestring = signature.join(':');\n\n            const hash = 'v0=' + crypto.createHmac('sha256', this.options.clientSigningSecret)\n                .update(basestring)\n                .digest('hex');\n            const retrievedSignature = req.header('X-Slack-Signature');\n\n            // Compare the hash of the computed signature with the retrieved signature with a secure hmac compare function\n            const validSignature = (): boolean => {\n                const slackSigBuffer = Buffer.from(retrievedSignature);\n                const compSigBuffer = Buffer.from(hash);\n\n                return crypto.timingSafeEqual(slackSigBuffer, compSigBuffer);\n            };\n\n            // replace direct compare with the hmac result\n            if (!validSignature()) {\n                debug('Signature verification failed, Ignoring message');\n                res.status(401);\n                res.end();\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    /**\n     * Accept an incoming webhook request and convert it into a TurnContext which can be processed by the bot's logic.\n     * @param req A request object from Restify or Express\n     * @param res A response object from Restify or Express\n     * @param logic A bot logic function in the form `async(context) => { ... }`\n     */\n    public async processActivity(req, res, logic: (context: TurnContext) => Promise<void>): Promise<void> {\n        // Create an Activity based on the incoming message from Slack.\n        // There are a few different types of event that Slack might send.\n        let event = req.body;\n\n        if (event.type === 'url_verification') {\n            res.status(200);\n            res.header('Content-Type: text/plain');\n            res.send(event.challenge);\n            return;\n        }\n\n        if (!await this.verifySignature(req, res)) {\n\n        } else if (event.payload) {\n            // handle interactive_message callbacks and block_actions\n\n            event = JSON.parse(event.payload);\n            if (this.options.verificationToken && event.token !== this.options.verificationToken) {\n                console.error('Rejected due to mismatched verificationToken:', event);\n                res.status(403);\n                res.end();\n            } else {\n                const activity = {\n                    timestamp: new Date(),\n                    channelId: 'slack',\n                    conversation: {\n                        id: event.channel ? event.channel.id : event.team.id, // use team id for channel id, required because modal block actions and submissions don't include channel.\n                        thread_ts: event.thread_ts,\n                        team: event.team.id\n                    },\n                    from: { id: event.user.id ?? event.bot_id },\n                    recipient: { id: null },\n                    channelData: event,\n                    type: ActivityTypes.Event,\n                    text: null\n                };\n\n                // If this is a message originating from a block_action or button click, we'll mark it as a message\n                // so it gets processed in BotkitConversations\n                if ((event.type === 'block_actions' || event.type === 'interactive_message') && event.actions) {\n                    activity.type = ActivityTypes.Message;\n                    switch (event.actions[0].type) {\n                    case 'button':\n                        activity.text = event.actions[0].value;\n                        break;\n                    case 'static_select':\n                    case 'external_select':\n                    case 'overflow':\n                        activity.text = event.actions[0].selected_option.value;\n                        break;\n                    case 'users_select':\n                        activity.text = event.actions[0].selected_user;\n                        break;\n                    case 'conversations_select':\n                        activity.text = event.actions[0].selected_conversation;\n                        break;\n                    case 'channels_select':\n                        activity.text = event.actions[0].selected_channel;\n                        break;\n                    case 'datepicker':\n                        activity.text = event.actions[0].selected_date;\n                        break;\n                    default: activity.text = event.actions[0].type;\n                    }\n                }\n\n                // @ts-ignore this complains because of extra fields in conversation\n                activity.recipient.id = await this.getBotUserByTeam(activity as Activity);\n\n                // create a conversation reference\n                // @ts-ignore\n                const context = new TurnContext(this, activity as Activity);\n\n                context.turnState.set('httpStatus', 200);\n\n                await this.runMiddleware(context, logic);\n\n                // send http response back\n                res.status(context.turnState.get('httpStatus'));\n                if (context.turnState.get('httpBody')) {\n                    res.send(context.turnState.get('httpBody'));\n                } else {\n                    res.end();\n                }\n            }\n        } else if (event.type === 'event_callback') {\n            // this is an event api post\n            if (this.options.verificationToken && event.token !== this.options.verificationToken) {\n                console.error('Rejected due to mismatched verificationToken:', event);\n                res.status(403);\n                res.end();\n            } else {\n                const activity = {\n                    id: event.event.ts ? event.event.ts : event.event.event_ts,\n                    timestamp: new Date(),\n                    channelId: 'slack',\n                    conversation: {\n                        id: event.event.channel ? event.event.channel : event.event.channel_id,\n                        thread_ts: event.event.thread_ts\n                    },\n                    from: { id: event.event.bot_id ? event.event.bot_id : event.event.user }, // TODO: bot_messages do not have a user field\n                    recipient: { id: null },\n                    channelData: event.event,\n                    text: null,\n                    type: ActivityTypes.Event\n                };\n\n                if (!activity.conversation.id) {\n                    // uhoh! this doesn't have a conversation id because it might have occurred outside a channel.\n                    // or be in reference to an item in a channel.\n                    if (event.event.item && event.event.item.channel) {\n                        activity.conversation.id = event.event.item.channel;\n                    } else {\n                        activity.conversation.id = event.team_id;\n                    }\n                }\n\n                // Copy over the authed_users\n                activity.channelData.authed_users = event.authed_users;\n\n                // @ts-ignore this complains because of extra fields in conversation\n                activity.recipient.id = await this.getBotUserByTeam(activity as Activity);\n\n                // Normalize the location of the team id\n                activity.channelData.team = event.team_id;\n\n                // add the team id to the conversation record\n                // @ts-ignore -- Tell Typescript to ignore this overload\n                activity.conversation.team = activity.channelData.team;\n\n                // If this is conclusively a message originating from a user, we'll mark it as such\n                if (event.event.type === 'message' && !event.event.subtype) {\n                    activity.type = ActivityTypes.Message;\n                    activity.text = event.event.text;\n                }\n\n                if (!activity.conversation.id) {\n                    console.error('Got Slack activity without a conversation id', event);\n                    return;\n                }\n\n                // create a conversation reference\n                // @ts-ignore\n                const context = new TurnContext(this, activity as Activity);\n\n                context.turnState.set('httpStatus', 200);\n\n                await this.runMiddleware(context, logic);\n\n                // send http response back\n                res.status(context.turnState.get('httpStatus'));\n                if (context.turnState.get('httpBody')) {\n                    res.send(context.turnState.get('httpBody'));\n                } else {\n                    res.end();\n                }\n            }\n        } else if (event.command) {\n            if (this.options.verificationToken && event.token !== this.options.verificationToken) {\n                console.error('Rejected due to mismatched verificationToken:', event);\n                res.status(403);\n                res.end();\n            } else {\n                // this is a slash command\n                const activity = {\n                    id: event.trigger_id,\n                    timestamp: new Date(),\n                    channelId: 'slack',\n                    conversation: {\n                        id: event.channel_id\n                    },\n                    from: { id: event.user_id },\n                    recipient: { id: null },\n                    channelData: event,\n                    text: event.text,\n                    type: ActivityTypes.Event\n                };\n\n                activity.recipient.id = await this.getBotUserByTeam(activity as Activity);\n\n                // Normalize the location of the team id\n                activity.channelData.team = event.team_id;\n\n                // add the team id to the conversation record\n                // @ts-ignore -- Tell Typescript to ignore this overload\n                activity.conversation.team = activity.channelData.team;\n\n                activity.channelData.botkitEventType = 'slash_command';\n\n                // create a conversation reference\n                // @ts-ignore\n                const context = new TurnContext(this, activity as Activity);\n\n                context.turnState.set('httpStatus', 200);\n\n                await this.runMiddleware(context, logic);\n\n                // send http response back\n                res.status(context.turnState.get('httpStatus'));\n                if (context.turnState.get('httpBody')) {\n                    res.send(context.turnState.get('httpBody'));\n                } else {\n                    res.end();\n                }\n            }\n        } else {\n            console.error('Unknown Slack event type: ', event);\n        }\n    }\n}\n\n/**\n * This interface defines the options that can be passed into the SlackAdapter constructor function.\n */\nexport interface SlackAdapterOptions {\n    /**\n     * Legacy method for validating the origin of incoming webhooks. Prefer `clientSigningSecret` instead.\n     */\n    verificationToken?: string;\n    /**\n     * A token used to validate that incoming webhooks originated with Slack.\n     */\n    clientSigningSecret?: string;\n    /**\n     * A token (provided by Slack) for a bot to work on a single workspace\n     */\n    botToken?: string;\n\n    /**\n     * The oauth client id provided by Slack for multi-team apps\n     */\n    clientId?: string;\n    /**\n     * The oauth client secret provided by Slack for multi-team apps\n     */\n    clientSecret?: string;\n    /**\n     * A array of scope names that are being requested during the oauth process. Must match the scopes defined at api.slack.com\n     */\n    scopes?: string[];\n    /**\n     * Which version of Slack's oauth protocol to use, v1 or v2. Defaults to v1.\n     */\n    oauthVersion?: string;\n    /**\n     * The URL users will be redirected to after an oauth flow. In most cases, should be `https://<mydomain.com>/install/auth`\n     */\n    redirectUri?: string;\n\n    /**\n     * A method that receives a Slack team id and returns the bot token associated with that team. Required for multi-team apps.\n     */\n    getTokenForTeam?: (teamId: string) => Promise<string>;\n\n    /**\n     * A method that receives a Slack team id and returns the bot user id associated with that team. Required for multi-team apps.\n     */\n    getBotUserByTeam?: (teamId: string) => Promise<string>;\n\n    /**\n     * Allow the adapter to startup without a complete configuration.\n     * This is risky as it may result in a non-functioning or insecure adapter.\n     * This should only be used when getting started.\n     */\n    enable_incomplete?: boolean;\n};\n\n// These interfaces are necessary to cast result of web api calls\n// See: http://slackapi.github.io/node-slack-sdk/typescript\ninterface ChatPostMessageResult extends WebAPICallResult {\n    channel: string;\n    ts: string;\n    message: {\n        text: string;\n    };\n}\n\n// These interfaces are necessary to cast result of web api calls\n// See: http://slackapi.github.io/node-slack-sdk/typescript\ninterface AuthTestResult extends WebAPICallResult {\n    user: string;\n    team: string;\n    team_id: string;\n    user_id: string;\n    ok: boolean;\n}\n"
  },
  {
    "path": "packages/botbuilder-adapter-slack/src/slack_dialog.ts",
    "content": "/**\n * @module botbuilder-adapter-slack\n */\n/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/**\n  * Create a Slack Dialog object for use with [replyWithDialog()](#replyWithDialog).\n  *\n  * ```javascript\n  * let dialog = new SlackDialog('My Dialog', 'callback_123', 'Save');\n  * dialog.addText('Your full name', 'name').addEmail('Your email', 'email');\n  * dialog.notifyOnCancel(true);\n  * bot.replyWithDialog(message, dialog.asObject());\n  * ```\n  *\n  */\nexport class SlackDialog {\n    private data: any;\n\n    /**\n     * Create a new dialog object\n     * @param title Title of dialog\n     * @param callback_id Callback id of dialog\n     * @param submit_label Label for the submit button\n     * @param elements An array of dialog elements\n     */\n    public constructor(title?: string, callback_id?: string, submit_label?: string, elements?: any) {\n        this.data = {\n            title: title,\n            callback_id: callback_id,\n            submit_label: submit_label || null,\n            elements: elements || []\n        };\n\n        return this;\n    }\n\n    /**\n     * Set the dialog's state field\n     * @param v value for state\n     */\n    public state(v): SlackDialog {\n        this.data.state = v;\n        return this;\n    }\n\n    /**\n     * Set true to have Slack notify you with a `dialog_cancellation` event if a user cancels the dialog without submitting\n     * @param set True or False\n     */\n    public notifyOnCancel(set: boolean): SlackDialog {\n        this.data.notify_on_cancel = set;\n        return this;\n    }\n\n    /**\n     * Set the title of the dialog\n     * @param v Value for title\n     */\n    public title(v: string): SlackDialog {\n        this.data.title = v;\n        return this;\n    }\n\n    /**\n     * Set the dialog's callback_id\n     * @param v Value for the callback_id\n     */\n    public callback_id(v: string): SlackDialog {\n        this.data.callback_id = v;\n        return this;\n    }\n\n    /**\n     * Set the button text for the submit button on the dialog\n     * @param v Value for the button label\n     */\n    public submit_label(v: string): SlackDialog {\n        this.data.submit_label = v;\n        return this;\n    }\n\n    /**\n     * Add a text input to the dialog\n     * @param label\n     * @param name\n     * @param value\n     * @param options\n     * @param subtype\n     */\n    public addText(label: string | any, name: string, value: string, options: string | any, subtype?: string): SlackDialog {\n        const element = (typeof (label) === 'object') ? label : {\n            label: label,\n            name: name,\n            value: value,\n            type: 'text',\n            subtype: subtype || null\n        };\n\n        if (typeof (options) === 'object') {\n            for (const key in options) {\n                element[key] = options[key];\n            }\n        }\n\n        this.data.elements.push(element);\n        return this;\n    }\n\n    /**\n     * Add an email input to the dialog\n     * @param label\n     * @param name\n     * @param value\n     * @param options\n     */\n    public addEmail(label: string, name: string, value: string, options?: any): SlackDialog {\n        return this.addText(label, name, value, options, 'email');\n    }\n\n    /**\n     * Add a number input to the dialog\n     * @param label\n     * @param name\n     * @param value\n     * @param options\n     */\n    public addNumber(label: string, name: string, value: string, options?: any): SlackDialog {\n        return this.addText(label, name, value, options, 'number');\n    }\n\n    /**\n     * Add a telephone number input to the dialog\n     * @param label\n     * @param name\n     * @param value\n     * @param options\n     */\n    public addTel(label: string, name: string, value: string, options?: any): SlackDialog {\n        return this.addText(label, name, value, options, 'tel');\n    }\n\n    /**\n     * Add a URL input to the dialog\n     * @param label\n     * @param name\n     * @param value\n     * @param options\n     */\n    public addUrl(label: string, name: string, value: string, options?: any): SlackDialog {\n        return this.addText(label, name, value, options, 'url');\n    }\n\n    /**\n     * Add a text area input to the dialog\n     * @param label\n     * @param name\n     * @param value\n     * @param options\n     * @param subtype\n     */\n    public addTextarea(label: string, name: string, value: string, options: any, subtype: string): SlackDialog {\n        const element = (typeof (label) === 'object') ? label : {\n            label: label,\n            name: name,\n            value: value,\n            type: 'textarea',\n            subtype: subtype || null\n        };\n\n        if (typeof (options) === 'object') {\n            for (const key in options) {\n                element[key] = options[key];\n            }\n        }\n\n        this.data.elements.push(element);\n        return this;\n    }\n\n    /**\n     * Add a dropdown select input to the dialog\n     * @param label\n     * @param name\n     * @param value\n     * @param option_list\n     * @param options\n     */\n    public addSelect(label: string, name: string, value: string | number | Record<string, any> | null, option_list: { label: string; value: string | number | Record<string, any> | null }[], options?: any): SlackDialog {\n        const element = {\n            label: label,\n            name: name,\n            value: value,\n            options: option_list,\n            type: 'select'\n        };\n        if (typeof (options) === 'object') {\n            for (const key in options) {\n                element[key] = options[key];\n            }\n        }\n\n        this.data.elements.push(element);\n        return this;\n    }\n\n    /**\n     * Get the dialog object as a JSON encoded string.\n     */\n    public asString(): string {\n        return JSON.stringify(this.data, null, 2);\n    }\n\n    /**\n     * Get the dialog object for use with bot.replyWithDialog()\n     */\n    public asObject(): any {\n        return this.data;\n    }\n}\n"
  },
  {
    "path": "packages/botbuilder-adapter-slack/src/slackevent_middleware.ts",
    "content": "/**\n * @module botbuilder-adapter-slack\n */\n/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ActivityTypes, MiddlewareSet, TurnContext } from 'botbuilder';\n\n/**\n * A middleware for Botkit developers using the BotBuilder SlackAdapter class.\n * This middleware causes Botkit to emit message events by their `type` or `subtype` field rather than their default BotBuilder Activity type (limited to message or event).\n * This keeps the new Botkit behavior consistent withprevious versions, and provides helpful filtering on the many event types that Slack sends.\n * To use this, bind it to the adapter before creating the Botkit controller:\n * ```javascript\n * const adapter = new SlackAdapter(options);\n * adapter.use(new SlackEventMiddleware());\n * const controller = new Botkit({\n *      adapter: adapter,\n *      // ...\n * });\n *\n * // can bind directly to channel_join (which starts as a message with type message and subtype channel_join)\n * controller.on('channel_join', async(bot, message) => {\n *  // send a welcome\n * });\n * ```\n */\nexport class SlackEventMiddleware extends MiddlewareSet {\n    /**\n     * Not for direct use - implements the MiddlewareSet's required onTurn function used to process the event\n     * @param context\n     * @param next\n     */\n    public async onTurn(context: TurnContext, next: () => Promise<any>): Promise<any> {\n        if (context.activity.type === ActivityTypes.Event && context.activity.channelData) {\n            // Handle message sub-types\n            if (context.activity.channelData.subtype) {\n                context.activity.channelData.botkitEventType = context.activity.channelData.subtype;\n            } else if (context.activity.channelData.type) {\n                context.activity.channelData.botkitEventType = context.activity.channelData.type;\n            }\n        }\n        await next();\n    }\n}\n"
  },
  {
    "path": "packages/botbuilder-adapter-slack/tests/SlackAdapter.tests.js",
    "content": "const assert = require('assert');\nconst { SlackAdapter } = require('../');\n\ndescribe('SlackAdapter', function() {\n\n    let adapter;\n\n    beforeEach(function () {\n        adapter = new SlackAdapter({\n            clientSigningSecret: '123',\n            clientId: '123',\n            clientSecret: '123',\n            scopes: ['bot'],\n            redirectUri: 'https://fake.com/install/auth',\n            getBotUserByTeam: async(team) => '123',\n            getTokenForTeam: async(team) => '123',\n        });\n    });\n\n    it('should not construct without required parameters', function () {\n        assert.throws(function () { let adapter = new SlackAdapter({}) }, 'Foo');\n    });\n\n    it('should create a SlackAdapter object', function () {\n        assert((adapter instanceof SlackAdapter), 'Adapter is wrong type');\n    });\n\n});\n"
  },
  {
    "path": "packages/botbuilder-adapter-slack/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2015\",\n    \"module\": \"commonjs\",\n    \"declaration\": true,\n    \"sourceMap\": true,\n    \"outDir\": \"./lib\",\n    \"rootDir\": \"./src\",\n    \"types\" : [\"node\"],\n    \"lib\": [\n      \"es5\",\n      \"es2015\",\n      \"es2016.array.include\",\n      \"esnext.asynciterable\",\n      \"dom\"\n    ]\n  },\n  \"include\": [\n    \"src/**/*\"\n  ]\n}"
  },
  {
    "path": "packages/botbuilder-adapter-twilio-sms/.eslintrc.js",
    "content": "module.exports = {\n    \"extends\": \"standard\",\n    \"rules\": {\n        \"semi\": [2, \"always\"],\n        \"indent\": [2, 4],\n        \"no-return-await\": 0,\n        \"camelcase\": 0,\n        \"no-unused-vars\": 0,\n        \"@typescript-eslint/indent\": 0,\n        \"@typescript-eslint/no-object-literal-type-assertion\": 0,\n        \"@typescript-eslint/explicit-member-accessibility\": 1,\n        \"space-before-function-paren\": [2, {\n            \"named\": \"never\",\n            \"anonymous\": \"never\",\n            \"asyncArrow\": \"always\"\n        }],\n        \"template-curly-spacing\": [2, \"always\"]\n    }\n};"
  },
  {
    "path": "packages/botbuilder-adapter-twilio-sms/.gitignore",
    "content": "node_modules/\n.env\nlib/\n.nyc_output/\n"
  },
  {
    "path": "packages/botbuilder-adapter-twilio-sms/CHANGELOG.md",
    "content": "# botbuilder-adapter-twilio changelog\n\n# 1.0.7\n\n* Update dependencies to Botkit 4.10, Bot Framework 4.10\n\n# 1.0.6\n\n* Update dependencies to Botkit 4.9, Bot Framework 4.9\n\n# 1.0.4\n\n* Update dependencies (Bot Framework to 4.6, Botkit to 4.6)\n\n# 1.0.2 \n\n* Update dependencies (Bot Framework to 4.5.2, Botkit to 4.5)\n\n# 1.0.1\n\n* Add `enable_incomplete` option to allow adapter to start without a complete config.\n\n# 1.0.0 \n\nfirst public release"
  },
  {
    "path": "packages/botbuilder-adapter-twilio-sms/LICENSE.md",
    "content": "Copyright XOXCO, Inc, http://xoxco.com, http://howdy.ai\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "packages/botbuilder-adapter-twilio-sms/package.json",
    "content": "{\n  \"name\": \"botbuilder-adapter-twilio-sms\",\n  \"version\": \"1.0.8\",\n  \"description\": \"Connect Botkit or BotBuilder to Twilio SMS\",\n  \"main\": \"./lib/index.js\",\n  \"typings\": \"./lib/index.d.ts\",\n  \"files\": [\n    \"/lib\",\n    \"/src\"\n  ],\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"test\": \"tsc ; nyc mocha tests/*.tests.js\",\n    \"eslint\": \"./node_modules/.bin/eslint --fix src/*\",\n    \"pack\": \"npm pack\"\n  },\n  \"author\": \"Microsoft Corp.\",\n  \"license\": \"MIT\",\n  \"keywords\": [\n    \"twilio\",\n    \"sms\",\n    \"twilio sms\",\n    \"texting\",\n    \"txting\",\n    \"botkit\",\n    \"botbuilder\",\n    \"botframework\",\n    \"bots\",\n    \"chatbots\",\n    \"azure\"\n  ],\n  \"homepage\": \"https://github.com/howdyai/botkit/blob/master/packages/botbuilder-adapter-twilio-sms#readme\",\n  \"bugs\": {\n    \"url\": \"https://github.com/howdyai/botkit/issues\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/howdyai/botkit.git\"\n  },\n  \"dependencies\": {\n    \"botbuilder\": \"^4.15.0\",\n    \"botkit\": \"^4.15.0\",\n    \"debug\": \"^4.1.0\",\n    \"twilio\": \"^3.29.2\"\n  },\n  \"devDependencies\": {\n    \"eslint\": \"^8.3.0\",\n    \"eslint-config-standard\": \"^16.0.3\",\n    \"eslint-plugin-import\": \"^2.25.3\",\n    \"eslint-plugin-node\": \"^11.1.0\",\n    \"eslint-plugin-promise\": \"^5.1.1\",\n    \"eslint-plugin-standard\": \"^4.0.1\"\n  }\n}\n"
  },
  {
    "path": "packages/botbuilder-adapter-twilio-sms/readme.md",
    "content": "# botbuilder-adapter-twilio-sms\n\nConnect [Botkit](https://www.npmjs.com/package/botkit) or [BotBuilder](https://www.npmjs.com/package/botbuilder) to Twilio SMS.\n\nThis package contains an adapter that communicates directly with the Twilio API,\nand translates messages to and from a standard format used by your bot. This package can be used alongside your favorite bot development framework to build bots that work with Twilio SMS.\n\n## Install Package\n\nAdd this package to your project using npm:\n\n```bash\nnpm install --save botbuilder-adapter-twilio-sms\n```\n\nImport the adapter class into your code:\n\n```javascript\nconst { TwilioAdapter } = require('botbuilder-adapter-twilio-sms');\n```\n\n## Get Started\n\nIf you are starting a brand new project, [follow these instructions to create a customized application template.](../docs/index.md)\n\n## Use TwilioAdapter in your App\n\nTwilioAdapter provides a translation layer for Botkit and BotBuilder so that bot developers can connect to Twilio SMS and have access to the Twilio API.\n\n### Botkit Basics\n\nWhen used in concert with Botkit, developers need only pass the configured adapter to the Botkit constructor, as seen below. Botkit will automatically create and configure the webhook endpoints and other options necessary for communicating with Twilio.\n\nDevelopers can then bind to Botkit's event emitting system using `controller.on` and `controller.hears` to filter and handle incoming events from the messaging platform. [Learn more about Botkit's core feature &rarr;](../docs/index.md).\n\n[A full description of the TwilioAdapter options and example code can be found in the class reference docs.](../docs/reference/twilio-sms.md#create-a-new-twilioadapter)\n\n```javascript\nconst adapter = new TwilioAdapter({\n    twilio_number: process.env.TWILIO_NUMBER,\n    account_sid: process.env.TWILIO_ACCOUNT_SID,\n    auth_token: process.env.TWILIO_AUTH_TOKEN,\n});\n\nconst controller = new Botkit({\n    adapter,\n    // ...other options\n});\n\ncontroller.on('message', async(bot, message) => {\n    await bot.reply(message, 'I heard a message!');\n});\n```\n\n### BotBuilder Basics\n\nAlternately, developers may choose to use `TwilioAdapter` with BotBuilder. With BotBuilder, the adapter is used more directly with a webserver, and all incoming events are handled as [Activities](https://docs.microsoft.com/en-us/javascript/api/botframework-schema/activity?view=botbuilder-ts-latest).\n\n```javascript\nconst adapter = new TwilioAdapter({\n    twilio_number: process.env.TWILIO_NUMBER,\n    account_sid: process.env.TWILIO_ACCOUNT_SID,\n    auth_token: process.env.TWILIO_AUTH_TOKEN,\n});\n\n\nconst server = restify.createServer();\nserver.use(restify.plugins.bodyParser());\nserver.post('/api/messages', (req, res) => {\n     adapter.processActivity(req, res, async(context) => {\n         await context.sendActivity('I heard a message!');\n     });\n});\n```\n\n## Class Reference\n\n* [TwilioAdapter](../docs/reference/twilio-sms.md#twilioadapter)\n* [BotWorker Extensions](../docs/reference/twilio-sms.md#twiliobotworker)\n\n## Event List\n\nBotkit will emit the following events: \n\n| Event | Description\n|--- |---\n| message | a message from a user\n| picture_message | a message with a picture attached\n\n## Calling Twilio APIs\n\nThis package exposes a pre-configured [Twilio API client](https://www.twilio.com/docs/libraries/node) for developers who want to use one of the many available API endpoints.\n\nIn Botkit handlers, the `bot` worker object passed into all handlers will contain a `bot.api` field that contains the client, preconfigured and ready to use.\n\n\n```javascript\ncontroller.on('message', async(bot, message) {\n\n    // create a message using the API directly\n    let res = await bot.api.messages.create(my_message_object);\n\n});\n```\n\n## Botkit Extensions\n\nIn Botkit handlers, the `bot` worker for Twilio contains [all of the base methods](../docs/reference/core.md#BotWorker) as well as the following platform-specific extensions:\n\n### [bot.startConversationWithUser()](../docs/reference/twilio-sms.md#startconversationwithuser)\n\nUse this method to initiate a conversation with a user. After calling this method, any further actions carried out by the bot worker will happen with the specified user.\n\nThis can be used to create or resume conversations with users that are not in direct response to an incoming message, like those sent on a schedule or in response to external events.\n\n## Community & Support\n\nJoin our thriving community of Botkit developers and bot enthusiasts at large.\nOver 10,000 members strong, [our open Slack group](https://community.botkit.ai) is\n_the place_ for people interested in the art and science of making bots.\nCome to ask questions, share your progress, and commune with your peers!\n\nYou can also find help from members of the Botkit team [in our dedicated Cisco Spark room](https://eurl.io/#SyNZuomKx)!\n\n## About Botkit\n\nBotkit is a part of the [Microsoft Bot Framework](https://dev.botframework.com).\n\nWant to contribute? [Read the contributor guide](https://github.com/howdyai/botkit/blob/master/CONTRIBUTING.md)\n\nBotkit is released under the [MIT Open Source license](https://github.com/howdyai/botkit/blob/master/LICENSE.md)\n"
  },
  {
    "path": "packages/botbuilder-adapter-twilio-sms/src/botworker.ts",
    "content": "/**\n * @module botbuilder-adapter-twilio-sms\n */\n/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { BotWorker } from 'botkit';\nimport * as Twilio from 'twilio';\nimport { ConversationAccount, ChannelAccount } from 'botbuilder';\n\n/**\n * This is a specialized version of [Botkit's core BotWorker class](core.md#BotWorker) that includes additional methods for interacting with Twilio SMS.\n * It includes all functionality from the base class, as well as the extension methods below.\n *\n * When using the TwilioAdapter with Botkit, all `bot` objects passed to handler functions will include these extensions.\n */export class TwilioBotWorker extends BotWorker {\n    /**\n     * A copy of the Twilio API client.\n     */\n    public api: Twilio.Twilio; // Twilio api\n\n    /**\n     * Start a conversation with a given user identified by their phone number. Useful for sending pro-active messages:\n     *\n     * ```javascript\n     * let bot = await controller.spawn();\n     * await bot.startConversationWithUser(MY_PHONE_NUMBER);\n     * await bot.send('An important update!');\n     * ```\n     *\n     * @param userId A phone number in the form +1XXXYYYZZZZ\n     */\n    public async startConversationWithUser(userId: string): Promise<any> {\n        return this.changeContext({\n            channelId: 'twilio-sms',\n            conversation: { id: userId } as ConversationAccount,\n            bot: { id: this.controller.getConfig('twilio_number'), name: 'bot' },\n            user: { id: userId } as ChannelAccount\n        });\n    }\n}\n"
  },
  {
    "path": "packages/botbuilder-adapter-twilio-sms/src/index.ts",
    "content": "/**\n * @module botbuilder-adapter-twilio-sms\n */\n/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport * from './twilio_adapter';\nexport * from './botworker';\n"
  },
  {
    "path": "packages/botbuilder-adapter-twilio-sms/src/twilio_adapter.ts",
    "content": "/**\n * @module botbuilder-adapter-twilio-sms\n */\n/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { Activity, ActivityTypes, BotAdapter, TurnContext, ConversationReference, ResourceResponse } from 'botbuilder';\nimport * as Debug from 'debug';\nimport * as Twilio from 'twilio';\nimport { TwilioBotWorker } from './botworker';\nconst debug = Debug('botkit:twilio');\n\n/**\n * Connect [Botkit](https://www.npmjs.com/package/botkit) or [BotBuilder](https://www.npmjs.com/package/botbuilder) to Twilio's SMS service.\n */\nexport class TwilioAdapter extends BotAdapter {\n    /**\n     * Name used by Botkit plugin loader\n     * @ignore\n     */\n    public name = 'Twilio SMS Adapter';\n\n    /**\n     * Object containing one or more Botkit middlewares to bind automatically.\n     * @ignore\n     */\n    public middlewares;\n\n    /**\n     * A specialized BotWorker for Botkit that exposes Twilio specific extension methods.\n     * @ignore\n     */\n    public botkit_worker = TwilioBotWorker;\n\n    private options: TwilioAdapterOptions;\n    private api: Twilio.Twilio; // Twilio api\n\n    /**\n     * Create an adapter to handle incoming messages from Twilio's SMS service and translate them into a standard format for processing by your bot.\n     *\n     * Use with Botkit:\n     *```javascript\n     * const adapter = new TwilioAdapter({\n     *      twilio_number: process.env.TWILIO_NUMBER,\n     *      account_sid: process.env.TWILIO_ACCOUNT_SID,\n     *      auth_token: process.env.TWILIO_AUTH_TOKEN,\n     *      validation_url: process.env.TWILIO_VALIDATION_URL\n     * });\n     * const controller = new Botkit({\n     *      adapter: adapter,\n     *      // ... other configuration options\n     * });\n     * ```\n     *\n     * Use with BotBuilder:\n     *```javascript\n     * const adapter = new TwilioAdapter({\n     *      twilio_number: process.env.TWILIO_NUMBER,\n     *      account_sid: process.env.TWILIO_ACCOUNT_SID,\n     *      auth_token: process.env.TWILIO_AUTH_TOKEN,\n     *      validation_url: process.env.TWILIO_VALIDATION_URL\n     * });\n     * // set up restify...\n     * const server = restify.createServer();\n     * server.use(restify.plugins.bodyParser());\n     * server.post('/api/messages', (req, res) => {\n     *      adapter.processActivity(req, res, async(context) => {\n     *          // do your bot logic here!\n     *      });\n     * });\n     * ```\n     *\n     * @param options An object containing API credentials, a webhook verification token and other options\n     */\n    public constructor(options: TwilioAdapterOptions) {\n        super();\n\n        this.options = options;\n\n        if (!options.twilio_number) {\n            const err = 'twilio_number is a required part of the configuration.';\n            if (!this.options.enable_incomplete) {\n                throw new Error(err);\n            } else {\n                console.error(err);\n            }\n        }\n        if (!options.account_sid) {\n            const err = 'account_sid  is a required part of the configuration.';\n            if (!this.options.enable_incomplete) {\n                throw new Error(err);\n            } else {\n                console.error(err);\n            }\n        }\n        if (!options.auth_token) {\n            const err = 'auth_token is a required part of the configuration.';\n            if (!this.options.enable_incomplete) {\n                throw new Error(err);\n            } else {\n                console.error(err);\n            }\n        }\n\n        if (this.options.enable_incomplete) {\n            const warning = [\n                '',\n                '****************************************************************************************',\n                '* WARNING: Your adapter may be running with an incomplete/unsafe configuration.        *',\n                '* - Ensure all required configuration options are present                              *',\n                '* - Disable the \"enable_incomplete\" option!                                            *',\n                '****************************************************************************************',\n                ''\n            ];\n            console.warn(warning.join('\\n'));\n        }\n\n        try {\n            this.api = Twilio(this.options.account_sid, this.options.auth_token);\n        } catch (err) {\n            if (err) {\n                if (!this.options.enable_incomplete) {\n                    throw new Error(err);\n                } else {\n                    console.error(err);\n                }\n            }\n        }\n\n        this.middlewares = {\n            spawn: [\n                async (bot, next): Promise<void> => {\n                    bot.api = this.api;\n                    next();\n                }\n            ]\n        };\n    }\n\n    /**\n     * Formats a BotBuilder activity into an outgoing Twilio SMS message.\n     * @param activity A BotBuilder Activity object\n     * @returns a Twilio message object with {body, from, to, mediaUrl}\n     */\n    private activityToTwilio(activity: Partial<Activity>): any {\n        const message = {\n            body: activity.text,\n            from: this.options.twilio_number,\n            to: activity.conversation.id,\n            mediaUrl: undefined\n        };\n\n        if (activity.channelData && activity.channelData.mediaUrl) {\n            message.mediaUrl = activity.channelData.mediaUrl;\n        }\n\n        return message;\n    }\n\n    /**\n     * Standard BotBuilder adapter method to send a message from the bot to the messaging API.\n     * [BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#sendactivities).\n     * @param context A TurnContext representing the current incoming message and environment. (Not used)\n     * @param activities An array of outgoing activities to be sent back to the messaging API.\n     */\n    public async sendActivities(context: TurnContext, activities: Partial<Activity>[]): Promise<ResourceResponse[]> {\n        const responses = [];\n        for (let a = 0; a < activities.length; a++) {\n            const activity = activities[a];\n            if (activity.type === ActivityTypes.Message) {\n                const message = this.activityToTwilio(activity as Activity);\n\n                const res = await this.api.messages.create(message);\n                responses.push({ id: res.sid });\n            } else {\n                debug('Unknown message type encountered in sendActivities: ', activity.type);\n            }\n        }\n\n        return responses;\n    }\n\n    /**\n     * Twilio SMS adapter does not support updateActivity.\n     * @ignore\n     */\n    // eslint-disable-next-line\n     public async updateActivity(context: TurnContext, activity: Partial<Activity>): Promise<void> {\n        debug('Twilio SMS does not support updating activities.');\n    }\n\n    /**\n     * Twilio SMS adapter does not support deleteActivity.\n     * @ignore\n     */\n    // eslint-disable-next-line\n     public async deleteActivity(context: TurnContext, reference: Partial<ConversationReference>): Promise<void> {\n        debug('Twilio SMS does not support deleting activities.');\n    }\n\n    /**\n     * Standard BotBuilder adapter method for continuing an existing conversation based on a conversation reference.\n     * [BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#continueconversation)\n     * @param reference A conversation reference to be applied to future messages.\n     * @param logic A bot logic function that will perform continuing action in the form `async(context) => { ... }`\n     */\n    public async continueConversation(reference: Partial<ConversationReference>, logic: (context: TurnContext) => Promise<void>): Promise<void> {\n        const request = TurnContext.applyConversationReference(\n            { type: 'event', name: 'continueConversation' },\n            reference,\n            true\n        );\n        const context = new TurnContext(this, request);\n\n        return this.runMiddleware(context, logic);\n    }\n\n    /**\n     * Accept an incoming webhook request and convert it into a TurnContext which can be processed by the bot's logic.\n     * @param req A request object from Restify or Express\n     * @param res A response object from Restify or Express\n     * @param logic A bot logic function in the form `async(context) => { ... }`\n     */\n    public async processActivity(req, res, logic: (context: TurnContext) => Promise<void>): Promise<void> {\n        if (await this.verifySignature(req, res) === true) {\n            const event = req.body;\n\n            const activity = {\n                id: event.MessageSid,\n                timestamp: new Date(),\n                channelId: 'twilio-sms',\n                conversation: {\n                    id: event.From\n                },\n                from: {\n                    id: event.From\n                },\n                recipient: {\n                    id: event.To\n                },\n                text: event.Body,\n                channelData: event,\n                type: ActivityTypes.Message\n            };\n\n            // Detect attachments\n            if (event.NumMedia && parseInt(event.NumMedia) > 0) {\n                // specify a different event type for Botkit\n                activity.channelData.botkitEventType = 'picture_message';\n            }\n\n            // create a conversation reference\n            const context = new TurnContext(this, activity as Activity);\n\n            context.turnState.set('httpStatus', 200);\n\n            await this.runMiddleware(context, logic);\n\n            // send http response back\n            res.status(context.turnState.get('httpStatus'));\n            if (context.turnState.get('httpBody')) {\n                res.send(context.turnState.get('httpBody'));\n            } else {\n                res.end();\n            }\n        }\n    }\n\n    /**\n     * Validate that requests are coming from Twilio\n     * @returns If signature is valid, returns true. Otherwise, sends a 400 error status via http response and then returns false.\n     */\n    private async verifySignature(req, res): Promise<any> {\n        let twilioSignature;\n        let validation_url;\n\n        // Restify style\n        if (!req.headers) {\n            twilioSignature = req.header('x-twilio-signature');\n\n            validation_url = this.options.validation_url ||\n                (req.headers['x-forwarded-proto'] || (req.isSecure()) ? 'https' : 'http') + '://' + req.headers.host + req.url;\n        } else {\n        // express style\n            twilioSignature = req.headers['x-twilio-signature'];\n\n            validation_url = this.options.validation_url ||\n                ((req.headers['x-forwarded-proto'] || req.protocol) + '://' + req.hostname + req.originalUrl);\n        }\n\n        if (twilioSignature && Twilio.validateRequest(this.options.auth_token, twilioSignature, validation_url, req.body)) {\n            return true;\n        } else {\n            debug('Signature verification failed, Ignoring message');\n            res.status(400);\n            res.send({\n                error: 'Invalid signature.'\n            });\n            return false;\n        }\n    }\n}\n\n/**\n * Parameters passed to the TwilioAdapter constructor.\n */\nexport interface TwilioAdapterOptions {\n    /**\n     * The phone number associated with this Twilio app, in the format 1XXXYYYZZZZ\n     */\n    twilio_number: string;\n    /**\n     * The account SID from the twilio account\n     */\n    account_sid: string;\n    /**\n     * An api auth token associated with the twilio account\n     */\n    auth_token: string;\n    /**\n     * An optional url to override the automatically generated url signature used to validate incoming requests -- [See Twilio docs about securing your endpoint.](https://www.twilio.com/docs/usage/security#validating-requests)\n     */\n    validation_url?: string;\n    /**\n     * Allow the adapter to startup without a complete configuration.\n     * This is risky as it may result in a non-functioning or insecure adapter.\n     * This should only be used when getting started.\n     */\n    enable_incomplete?: boolean;\n\n}\n"
  },
  {
    "path": "packages/botbuilder-adapter-twilio-sms/tests/TwilioAdapter.tests.js",
    "content": "const assert = require('assert');\nconst { TwilioAdapter } = require('../');\n\ndescribe('TwilioAdapter', function() {\n\n    let adapter;\n\n    beforeEach(function () {\n        adapter = new TwilioAdapter({\n            twilio_number: '14155551212',\n            account_sid: 'AC123123',\n            auth_token: '123123',\n        });\n    });\n\n    it('should not construct without required parameters', function () {\n        assert.throws(function () { let adapter = new TwilioAdapter({}) }, 'Foo');\n    });\n\n    it('should create a TwilioAdapter object', function () {\n        assert((adapter instanceof TwilioAdapter), 'Adapter is wrong type');\n    });\n\n});\n"
  },
  {
    "path": "packages/botbuilder-adapter-twilio-sms/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2015\",\n    \"module\": \"commonjs\",\n    \"declaration\": true,\n    \"sourceMap\": true,\n    \"outDir\": \"./lib\",\n    \"rootDir\": \"./src\",\n    \"types\" : [\"node\"],\n    \"lib\": [\n      \"es5\",\n      \"es2015\",\n      \"es2016.array.include\",\n      \"esnext.asynciterable\",\n      \"dom\"\n    ]\n  },\n  \"include\": [\n    \"src/**/*\"\n  ]\n}"
  },
  {
    "path": "packages/botbuilder-adapter-web/.eslintrc.js",
    "content": "module.exports = {\n    \"extends\": \"standard\",\n    \"rules\": {\n        \"semi\": [2, \"always\"],\n        \"indent\": [2, 4],\n        \"no-return-await\": 0,\n        \"camelcase\": 0,\n        \"no-unused-vars\": 0,\n        \"@typescript-eslint/ban-ts-ignore\": 1,\n        \"@typescript-eslint/no-object-literal-type-assertion\": 0,\n        \"@typescript-eslint/indent\": 0,\n        \"@typescript-eslint/explicit-member-accessibility\": 1,\n        \"space-before-function-paren\": [2, {\n            \"named\": \"never\",\n            \"anonymous\": \"never\",\n            \"asyncArrow\": \"always\"\n        }],\n        \"template-curly-spacing\": [2, \"always\"]\n    }\n};"
  },
  {
    "path": "packages/botbuilder-adapter-web/.gitignore",
    "content": "node_modules/\n.env\nlib/\n.nyc_output/\n"
  },
  {
    "path": "packages/botbuilder-adapter-web/CHANGELOG.md",
    "content": "# botbuilder-adapter-web changelog\n\n# 1.0.9\n\n* Update dependencies to Botkit 4.10, Bot Framework 4.10\n\n* Fix to websocket ping call. [Issue #2003](https://github.com/howdyai/botkit/issues/2003)\n\n# 1.0.8\n\n* Update dependencies to Botkit 4.9, Bot Framework 4.9\n\n# 1.0.6\n\n* Update dependencies on Bot Framework and Botkit\n* Fix syntax error in sample client - Thanks @naktibalda! [#1881](https://github.com/howdyai/botkit/pull/1881)\n\n# 1.0.5\n\n* Update dependencies (Bot Framework to 4.6, Botkit to 4.6)\n\n# 1.0.4\n\n* Update dependencies (Bot Framework to 4.5.2, Botkit to 4.5, WS to 7.1.1)\n\n# 1.0.3\n\n* Fix - will not attempt to send a message if socket is closed. - Thanks [@naktibalda](https://github.com/Naktibalda) for [the fix](https://github.com/howdyai/botkit/pull/1657)\n* Add getConnection method() - Thanks to [@naktibalda](https://github.com/Naktibalda) for [the contribution](https://github.com/howdyai/botkit/pull/1666)\n\n# 1.0.2\n\n* Add [isConnected()](https://botkit.ai/docs/v4/reference/web.html#isconnected) method to WebAdapter. This allows a bot to check the status of a (potentially stale) websocket connection before sending messages. Thanks to [@Naktibalda](https://github.com/Naktibalda) for [this contribution](https://github.com/howdyai/botkit/pull/1644).\n\n# 1.0.1\n\nThis was the first public release!"
  },
  {
    "path": "packages/botbuilder-adapter-web/LICENSE.md",
    "content": "Copyright XOXCO, Inc, http://xoxco.com, http://howdy.ai\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "packages/botbuilder-adapter-web/client/client.js",
    "content": "/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nvar converter = new showdown.Converter();\nconverter.setOption('openLinksInNewWindow', true);\n\nvar Botkit = {\n    config: {\n        ws_url: (location.protocol === 'https:' ? 'wss' : 'ws') + '://' + location.host,\n        reconnect_timeout: 3000,\n        max_reconnect: 5,\n        enable_history: false,\n    },\n    options: {\n        use_sockets: true,\n    },\n    reconnect_count: 0,\n    guid: null,\n    current_user: null,\n    on: function (event, handler) {\n        this.message_window.addEventListener(event, function (evt) {\n            handler(evt.detail);\n        });\n    },\n    trigger: function (event, details) {\n        var event = new CustomEvent(event, {\n            detail: details\n        });\n        this.message_window.dispatchEvent(event);\n    },\n    request: function (url, body) {\n        var that = this;\n        return new Promise(function (resolve, reject) {\n            var xmlhttp = new XMLHttpRequest();\n\n            xmlhttp.onreadystatechange = function () {\n                if (xmlhttp.readyState == XMLHttpRequest.DONE) {\n                    if (xmlhttp.status == 200) {\n                        var response = xmlhttp.responseText;\n                        if (response !='') {\n                            var message = null;\n                            try {\n                                message = JSON.parse(response);\n                            } catch (err) {\n                                reject(err);\n                                return;\n                            }\n                            resolve(message);\n                        } else {\n                            resolve([]);\n                        }\n                    } else {\n                        reject(new Error('status_' + xmlhttp.status));\n                    }\n                }\n            };\n\n            xmlhttp.open(\"POST\", url, true);\n            xmlhttp.setRequestHeader(\"Content-Type\", \"application/json\");\n            xmlhttp.send(JSON.stringify(body));\n        });\n\n    },\n    send: function (text, e) {\n        var that = this;\n        if (e) e.preventDefault();\n        if (!text) {\n            return;\n        }\n        var message = {\n            type: 'outgoing',\n            text: text\n        };\n\n        this.clearReplies();\n        that.renderMessage(message);\n\n        that.deliverMessage({\n            type: 'message',\n            text: text,\n            user: this.guid,\n            channel: this.options.use_sockets ? 'websocket' : 'webhook'\n        });\n\n        this.input.value = '';\n\n        this.trigger('sent', message);\n\n        return false;\n    },\n    deliverMessage: function (message) {\n        if (this.options.use_sockets) {\n            this.socket.send(JSON.stringify(message));\n        } else {\n            this.webhook(message);\n        }\n    },\n    getHistory: function (guid) {\n        var that = this;\n        if (that.guid) {\n            that.request('/botkit/history', {\n                user: that.guid\n            }).then(function (history) {\n                if (history.success) {\n                    that.trigger('history_loaded', history.history);\n                } else {\n                    that.trigger('history_error', new Error(history.error));\n                }\n            }).catch(function (err) {\n                that.trigger('history_error', err);\n            });\n        }\n    },\n    webhook: function (message) {\n        var that = this;\n\n        that.request('/api/messages', message).then(function (messages) {\n            messages.forEach((message) => {\n                that.trigger(message.type, message);\n            });\n        }).catch(function (err) {\n            that.trigger('webhook_error', err);\n        });\n\n    },\n    connect: function (user) {\n\n        var that = this;\n\n        if (user && user.id) {\n            Botkit.setCookie('botkit_guid', user.id, 1);\n\n            user.timezone_offset = new Date().getTimezoneOffset();\n            that.current_user = user;\n            console.log('CONNECT WITH USER', user);\n        }\n\n        // connect to the chat server!\n        if (that.options.use_sockets) {\n            that.connectWebsocket(that.config.ws_url);\n        } else {\n            that.connectWebhook();\n        }\n\n    },\n    connectWebhook: function () {\n        var that = this;\n        var connectEvent = 'hello';\n        if (Botkit.getCookie('botkit_guid')) {\n            that.guid = Botkit.getCookie('botkit_guid');\n            connectEvent = 'welcome_back';\n        } else {\n            that.guid = that.generate_guid();\n            Botkit.setCookie('botkit_guid', that.guid, 1);\n        }\n\n        if (this.options.enable_history) {\n            that.getHistory();\n        }\n\n        // connect immediately\n        that.trigger('connected', {});\n        that.webhook({\n            type: connectEvent,\n            user: that.guid,\n            channel: 'webhook',\n        });\n\n    },\n    connectWebsocket: function (ws_url) {\n        var that = this;\n        // Create WebSocket connection.\n        that.socket = new WebSocket(ws_url);\n\n        var connectEvent = 'hello';\n        if (Botkit.getCookie('botkit_guid')) {\n            that.guid = Botkit.getCookie('botkit_guid');\n            connectEvent = 'welcome_back';\n        } else {\n            that.guid = that.generate_guid();\n            Botkit.setCookie('botkit_guid', that.guid, 1);\n        }\n\n        if (this.options.enable_history) {\n            that.getHistory();\n        }\n\n        // Connection opened\n        that.socket.addEventListener('open', function (event) {\n            console.log('CONNECTED TO SOCKET');\n            that.reconnect_count = 0;\n            that.trigger('connected', event);\n            that.deliverMessage({\n                type: connectEvent,\n                user: that.guid,\n                channel: 'socket',\n                user_profile: that.current_user ? that.current_user : null,\n            });\n        });\n\n        that.socket.addEventListener('error', function (event) {\n            console.error('ERROR', event);\n        });\n\n        that.socket.addEventListener('close', function (event) {\n            console.log('SOCKET CLOSED!');\n            that.trigger('disconnected', event);\n            if (that.reconnect_count < that.config.max_reconnect) {\n                setTimeout(function () {\n                    console.log('RECONNECTING ATTEMPT ', ++that.reconnect_count);\n                    that.connectWebsocket(that.config.ws_url);\n                }, that.config.reconnect_timeout);\n            } else {\n                that.message_window.className = 'offline';\n            }\n        });\n\n        // Listen for messages\n        that.socket.addEventListener('message', function (event) {\n            var message = null;\n            try {\n                message = JSON.parse(event.data);\n            } catch (err) {\n                that.trigger('socket_error', err);\n                return;\n            }\n\n            that.trigger(message.type, message);\n        });\n    },\n    clearReplies: function () {\n        this.replies.innerHTML = '';\n    },\n    quickReply: function (payload) {\n        this.send(payload);\n    },\n    focus: function () {\n        this.input.focus();\n    },\n    renderMessage: function (message) {\n        var that = this;\n        if (!that.next_line) {\n            that.next_line = document.createElement('div');\n            that.message_list.appendChild(that.next_line);\n        }\n        if (message.text) {\n            message.html = converter.makeHtml(message.text);\n        }\n\n        that.next_line.innerHTML = that.message_template({\n            message: message\n        });\n        if (!message.isTyping) {\n            delete (that.next_line);\n        }\n    },\n    triggerScript: function (script, thread) {\n        this.deliverMessage({\n            type: 'trigger',\n            user: this.guid,\n            channel: this.options.use_sockets ? 'websocket' : 'webhook',\n            script: script,\n            thread: thread\n        });\n    },\n    identifyUser: function (user) {\n\n        user.timezone_offset = new Date().getTimezoneOffset();\n\n        this.guid = user.id;\n        Botkit.setCookie('botkit_guid', user.id, 1);\n\n        this.current_user = user;\n\n        this.deliverMessage({\n            type: 'identify',\n            user: this.guid,\n            channel: this.options.use_sockets ? 'websocket' : 'webhook',\n            user_profile: user,\n        });\n    },\n    receiveCommand: function (event) {\n        switch (event.data.name) {\n            case 'trigger':\n                // tell Botkit to trigger a specific script/thread\n                console.log('TRIGGER', event.data.script, event.data.thread);\n                Botkit.triggerScript(event.data.script, event.data.thread);\n                break;\n            case 'identify':\n                // link this account info to this user\n                console.log('IDENTIFY', event.data.user);\n                Botkit.identifyUser(event.data.user);\n                break;\n            case 'connect':\n                // link this account info to this user\n                Botkit.connect(event.data.user);\n                break;\n            default:\n                console.log('UNKNOWN COMMAND', event.data);\n        }\n    },\n    sendEvent: function (event) {\n\n        if (this.parent_window) {\n            this.parent_window.postMessage(event, '*');\n        }\n\n    },\n    setCookie: function (cname, cvalue, exdays) {\n        var d = new Date();\n        d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));\n        var expires = \"expires=\" + d.toUTCString();\n        document.cookie = cname + \"=\" + cvalue + \";\" + expires + \";path=/\";\n    },\n    getCookie: function (cname) {\n        var name = cname + \"=\";\n        var decodedCookie = decodeURIComponent(document.cookie);\n        var ca = decodedCookie.split(';');\n        for (var i = 0; i < ca.length; i++) {\n            var c = ca[i];\n            while (c.charAt(0) == ' ') {\n                c = c.substring(1);\n            }\n            if (c.indexOf(name) == 0) {\n                return c.substring(name.length, c.length);\n            }\n        }\n        return \"\";\n    },\n    generate_guid: function () {\n        function s4() {\n            return Math.floor((1 + Math.random()) * 0x10000)\n                .toString(16)\n                .substring(1);\n        }\n        return s4() + s4() + '-' + s4() + '-' + s4() + '-' +\n            s4() + '-' + s4() + s4() + s4();\n    },\n    boot: function (user) {\n\n        console.log('Booting up');\n\n        var that = this;\n\n\n        that.message_window = document.getElementById(\"message_window\");\n\n        that.message_list = document.getElementById(\"message_list\");\n\n        var source = document.getElementById('message_template').innerHTML;\n        that.message_template = Handlebars.compile(source);\n\n        that.replies = document.getElementById('message_replies');\n\n        that.input = document.getElementById('messenger_input');\n\n        that.focus();\n\n        that.on('connected', function () {\n            that.message_window.className = 'connected';\n            that.input.disabled = false;\n            that.sendEvent({\n                name: 'connected'\n            });\n        })\n\n        that.on('disconnected', function () {\n            that.message_window.className = 'disconnected';\n            that.input.disabled = true;\n        });\n\n        that.on('webhook_error', function (err) {\n\n            alert('Error sending message!');\n            console.error('Webhook Error', err);\n\n        });\n\n        that.on('typing', function () {\n            that.clearReplies();\n            that.renderMessage({\n                isTyping: true\n            });\n        });\n\n        that.on('sent', function () {\n            // do something after sending\n        });\n\n        that.on('message', function (message) {\n\n            console.log('RECEIVED MESSAGE', message);\n            that.renderMessage(message);\n\n        });\n\n        that.on('message', function (message) {\n            if (message.goto_link) {\n                window.location = message.goto_link;\n            }\n        });\n\n\n        that.on('message', function (message) {\n            that.clearReplies();\n            if (message.quick_replies) {\n\n                var list = document.createElement('ul');\n\n                var elements = [];\n                for (var r = 0; r < message.quick_replies.length; r++) {\n                    (function (reply) {\n\n                        var li = document.createElement('li');\n                        var el = document.createElement('a');\n                        el.innerHTML = reply.title;\n                        el.href = '#';\n\n                        el.onclick = function () {\n                            that.quickReply(reply.payload);\n                        }\n\n                        li.appendChild(el);\n                        list.appendChild(li);\n                        elements.push(li);\n\n                    })(message.quick_replies[r]);\n                }\n\n                that.replies.appendChild(list);\n\n                // uncomment this code if you want your quick replies to scroll horizontally instead of stacking\n                // var width = 0;\n                // // resize this element so it will scroll horizontally\n                // for (var e = 0; e < elements.length; e++) {\n                //     width = width + elements[e].offsetWidth + 18;\n                // }\n                // list.style.width = width + 'px';\n\n                if (message.disable_input) {\n                    that.input.disabled = true;\n                } else {\n                    that.input.disabled = false;\n                }\n            } else {\n                that.input.disabled = false;\n            }\n        });\n\n        that.on('history_loaded', function (history) {\n            if (history) {\n                for (var m = 0; m < history.length; m++) {\n                    that.renderMessage({\n                        text: history[m].text,\n                        type: history[m].type == 'message_received' ? 'outgoing' : 'incoming', // set appropriate CSS class\n                    });\n                }\n            }\n        });\n\n\n        if (window.self !== window.top) {\n            // this is embedded in an iframe.\n            // send a message to the master frame to tell it that the chat client is ready\n            // do NOT automatically connect... rather wait for the connect command.\n            that.parent_window = window.parent;\n            window.addEventListener(\"message\", that.receiveCommand, false);\n            that.sendEvent({\n                type: 'event',\n                name: 'booted'\n            });\n            console.log('Messenger booted in embedded mode');\n\n        } else {\n\n            console.log('Messenger booted in stand-alone mode');\n            // this is a stand-alone client. connect immediately.\n            that.connect(user);\n        }\n\n        return that;\n    }\n};\n\n\n(function () {\n    // your page initialization code here\n    // the DOM will be available here\n    Botkit.boot();\n})();\n"
  },
  {
    "path": "packages/botbuilder-adapter-web/client/css/embed.css",
    "content": "#embedded_messenger {\n  position: fixed;\n  z-index: 1000;\n  bottom: -400px;\n  right: 2rem;\n  height: 434px;\n  transition: 0.5s ease-in-out bottom;\n}\n#embedded_messenger.active {\n  bottom: 0;\n}\n#embedded_messenger iframe {\n  height: 400px;\n  width: 100%;\n  border: 0;\n}\n#embedded_messenger #message_header {\n  background: #000;\n  padding: 0.5rem 1rem;\n  color: #FFF;\n}\n\n/*# sourceMappingURL=embed.css.map */\n"
  },
  {
    "path": "packages/botbuilder-adapter-web/client/css/styles.css",
    "content": "/* shared botkit ui styles */\n* {\n  box-sizing: border-box;\n}\n\nbody,\nhtml {\n  margin: 0;\n  padding: 0;\n  font-size: 18px;\n  background-color: #FFF;\n  font-family: \"helvetica\", sans-serif;\n}\n\n.wrapper {\n  position: relative;\n  max-width: 1000px;\n  margin: 0 auto;\n}\n.wrapper:after {\n  content: \"\";\n  display: table;\n  clear: both;\n}\n\n.box {\n  border: 2px solid #CCC;\n  padding: 1rem calc(1rem - 2px);\n  margin-bottom: 1rem;\n}\n.box:after {\n  content: \"\";\n  display: table;\n  clear: both;\n}\n.box h1,\n.box h2,\n.box h3 {\n  margin-top: 0;\n}\n\nfooter {\n  text-align: center;\n}\n\n.hero {\n  text-align: center;\n  padding: 2rem;\n}\n.hero h1 {\n  font-size: 4rem;\n  margin: 0;\n}\n\na {\n  color: #a795ef;\n}\n\n.copyurl {\n  width: 100%;\n  font-size: 1.25rem;\n}\n\ndiv.input label {\n  font-weight: bold;\n  font-size: smaller;\n}\n\n.addon {\n  display: flex;\n  border: 1px solid #999;\n  border-radius: 6px;\n  padding: 5px;\n  background: #F0F0F0;\n}\n.addon input,\n.addon textarea {\n  flex-grow: 1;\n  border: 0;\n  background: transparent;\n}\n.addon button {\n  flex-grow: 0;\n  background: transparent;\n  border: 1px solid #999;\n  border-radius: 6px;\n  font-weight: bold;\n}\n.addon button.textarea {\n  align-self: flex-start;\n  padding: 0.5rem;\n}\n.addon button:hover {\n  background: #FFF;\n  color: #a795ef;\n}\n\ndiv.hr {\n  border: 1px dashed #ccc;\n  width: 10%;\n  margin: 4rem auto;\n  height: 1px;\n}\n\na.button {\n  border: 2px solid #a795ef;\n  font-weight: bold;\n  margin: 0;\n  border-radius: 3px;\n  display: inline-block;\n  padding: 0.5rem 2rem;\n  text-align: center;\n  text-decoration: none;\n  box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.2);\n  background-color: #FFF;\n  transition: box-shadow 0.1s linear;\n}\na.button:hover {\n  box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.1);\n}\n\n/* chat client */\n#message_window {\n  background: #FFFFFF;\n  border-left: 1px solid #CCC;\n  border-right: 1px solid #CCC;\n  /*height: 500px;\n  width: 320px;*/\n  height: 100%;\n  width: 100%;\n  /*margin: 2rem auto;*/\n  display: flex;\n  flex-direction: column;\n  font-family: \"helvetica\", sans-serif;\n}\n#message_window .disconnected {\n  background: #FFFFCC;\n  padding: 0.25rem;\n}\n#message_window.connected .disconnected {\n  display: none;\n}\n#message_window .offline {\n  display: none;\n}\n#message_window.offline .disconnected {\n  display: none;\n}\n#message_window.offline .offline {\n  background: #FF0000;\n  color: #FFF;\n  padding: 0.25rem;\n  display: block;\n}\n#message_window .powered_by {\n  flex-shrink: 0;\n  text-align: center;\n  border-bottom: 1px solid #CCC;\n  font-size: 14px;\n  padding: 0.25rem;\n  color: #666;\n}\n#message_window .powered_by a {\n  text-decoration: none;\n  color: #666;\n}\n#message_window .powered_by img {\n  position: relative;\n  top: 2px;\n}\n#message_window section {\n  flex-grow: 1;\n  flex-direction: column-reverse;\n  display: flex;\n  overflow-y: auto;\n}\n#message_window section div div {\n  margin: 0.25rem;\n  clear: both;\n}\n#message_window footer {\n  border-top: 1px solid #CCC;\n  padding: 0.25rem;\n}\n#message_window footer input[type=text] {\n  flex-grow: 1;\n  font-size: 1.25rem;\n  outline: none;\n  border: none;\n}\n#message_window footer button {\n  width: 50px;\n  background: none;\n  border: 0;\n  cursor: pointer;\n  color: blue;\n  font-weight: bold;\n}\n#message_window form {\n  display: flex;\n  margin: 0;\n  padding: 0.25rem;\n}\n#message_window #message_template {\n  display: none;\n}\n#message_window .message {\n  font-size: 14px;\n  padding: 0.5rem;\n  background: #F0F0F0;\n  color: #333;\n  border-radius: 5px;\n  width: auto;\n  display: inline-block;\n  max-width: 75%;\n}\n#message_window .file_attachment {\n  background: #F0F0F0;\n  color: #333;\n  border-radius: 5px;\n  display: inline-block;\n  max-width: 75%;\n}\n#message_window .file_attachment img {\n  max-width: 100%;\n  display: block;\n}\n#message_window .button_message {\n  margin: 1rem 0;\n  border-radius: 4px;\n  border-color: orange;\n  border-style: solid;\n  color: orange;\n  border-width: 1px;\n  padding: 0.25rem 1rem;\n  text-decoration: none;\n  text-align: center;\n  box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.25);\n  display: block;\n}\n#message_window .message p {\n  margin-top: 0;\n  margin-bottom: 0.5rem;\n}\n#message_window .message p:last-child {\n  margin-bottom: 0;\n}\n#message_window .message.outgoing {\n  float: right;\n  background: #a795ef;\n  color: white;\n}\n#message_window #message_replies {\n  text-align: center;\n  overflow-x: auto;\n  flex-shrink: 0;\n  -webkit-overflow-scrolling: touch;\n  /* Lets it scroll lazy */\n}\n#message_window #message_replies ul {\n  list-style-type: none;\n  margin: 0px auto;\n  padding: 0;\n}\n#message_window #message_replies ul li {\n  display: inline-block;\n  margin: 0.5rem;\n  margin-left: 0;\n}\n#message_window #message_replies a {\n  text-decoration: none;\n  display: block;\n  border: 1px solid #a795ef;\n  color: #a795ef;\n  border-radius: 16px;\n  padding: 0.25rem 1rem;\n  font-size: 14px;\n  cursor: pointer;\n}\n#message_window #message_replies a:hover {\n  background: #a795ef;\n  color: #FFF;\n}\n\n/* typing indicator CSS based on code by Joseph Fusco -> https://codepen.io/fusco/pen/XbpaYv */\n.typing-indicator {\n  display: table;\n  margin: 0 auto;\n  position: relative;\n}\n.typing-indicator span {\n  height: 5px;\n  width: 5px;\n  float: left;\n  margin: 0 1px;\n  background-color: #333;\n  display: block;\n  border-radius: 50%;\n  opacity: 0.4;\n}\n.typing-indicator span:nth-of-type(1) {\n  animation: 1s blink infinite 0.3333s;\n}\n.typing-indicator span:nth-of-type(2) {\n  animation: 1s blink infinite 0.6666s;\n}\n.typing-indicator span:nth-of-type(3) {\n  animation: 1s blink infinite 0.9999s;\n}\n\n@keyframes blink {\n  50% {\n    opacity: 1;\n  }\n}\n/* special styles for homepage */\n#home {\n  position: relative;\n  max-width: 650px;\n  margin: auto;\n}\n#home:after {\n  content: \"\";\n  display: table;\n  clear: both;\n}\n\n#homepage_bot {\n  width: 400px;\n  height: 450px;\n  float: left;\n  border: 5px solid #333;\n  box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.5);\n}\n#homepage_bot iframe {\n  border: 0;\n  height: 100%;\n  width: 100%;\n}\n\n#welcome {\n  margin-left: 440px;\n}\n\n/*# sourceMappingURL=styles.css.map */\n"
  },
  {
    "path": "packages/botbuilder-adapter-web/client/embed.js",
    "content": "var Botkit = {\n\n    setCookie: function(cname, cvalue, exdays) {\n      var d = new Date();\n      d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));\n      var expires = \"expires=\" + d.toUTCString();\n      document.cookie = cname + \"=\" + cvalue + \";\" + expires + \";path=/\";\n    },\n    getCookie: function(cname) {\n      var name = cname + \"=\";\n      var decodedCookie = decodeURIComponent(document.cookie);\n      var ca = decodedCookie.split(';');\n      for (var i = 0; i < ca.length; i++) {\n        var c = ca[i];\n        while (c.charAt(0) == ' ') {\n          c = c.substring(1);\n        }\n        if (c.indexOf(name) == 0) {\n          return c.substring(name.length, c.length);\n        }\n      }\n      return \"\";\n    },\n    active: false,\n    activate: function() {\n      this.active = true;\n      if (this.container) {\n        this.container.className = 'active';\n      }\n      this.setCookie('botkit_messenger_active', this.active);\n    },\n    deactivate: function() {\n      this.active = false;\n      if (this.container) {\n        this.container.className = '';\n      }\n      this.setCookie('botkit_messenger_active', this.active);\n    },\n    toggle: function() {\n      if (this.active) {\n        this.deactivate();\n      } else {\n        this.activate();\n      }\n    },\n    trigger: function(event) {\n      this.chatClient.postMessage(event, '*');\n    },\n    receiveMessage: function(message) {\n      // message contains the following fields:\n      // message.data, message.origin, message.source\n  \n      switch (message.data.name) {\n        case 'booted':\n          Botkit.trigger({\n            name: 'connect',\n            user: Botkit.current_user ? Botkit.current_user : null,\n          });\n  \n          if (Botkit.getCookie('botkit_messenger_active') == 'true') {\n            Botkit.activate();\n          }\n          console.log('Embedded Botkit: Ready!');\n          break;\n        case 'connected':\n          // console.log('100% CONNECTED AND READY TO GO');\n          break;\n      }\n    },\n    triggerScript: function(script, thread) {\n  \n      this.trigger({\n        type: 'event',\n        name: 'trigger',\n        script: script,\n        thread: thread,\n      });\n    },\n    identifyUser: function(user) {\n  \n      // user should contain any of the following:\n      // id, email, name, first_name, last_name, full_name, gender, timezone, timezone_offset\n  \n      this.current_user = user;\n  \n      this.trigger({\n        type: 'event',\n        name: 'identify',\n        user: user,\n      });\n  \n  \n    },\n    boot: function(user) {\n      var that = this;\n  \n      that.container = document.getElementById('embedded_messenger');\n      that.header = document.getElementById('messenger_header');\n      that.chatClient = document.getElementById('botkit_client').contentWindow;\n  \n      if (user) {\n        that.current_user = user;\n      }\n  \n      if (!that.chatClient) {\n        console.error('Cannot find Botkit chat client iframe. Make sure your iframe has the id #botkit_client');\n      }\n  \n      window.addEventListener('message', that.receiveMessage, false);\n  \n      return this;\n    }\n  }\n  "
  },
  {
    "path": "packages/botbuilder-adapter-web/client/index.html",
    "content": "<html>\n    <head>\n        <title>Botkit Anywhere</title>\n        <script src=\"https://cdn.polyfill.io/v3/polyfill.min.js\"></script>\n        <script src=\"https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.10/handlebars.min.js\"></script>\n        <script src=\"https://cdn.rawgit.com/showdownjs/showdown/1.7.4/dist/showdown.min.js\"></script>\n        <link rel=\"stylesheet\" href=\"/css/styles.css\" />\n        <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    </head>\n    <body >\n      <div class=\"wrapper\">\n\n        <div id=\"message_window\">\n            <div class=\"disconnected\">\n                Disconnected... reconnecting!\n            </div>\n            <div class=\"offline\">\n                Offline! Reload to reconnect.\n            </div>\n            <div class=\"powered_by\">\n              Powered by <a href=\"https://github.com/howdyai/botkit\" target=\"_blank\" title=\"Building Blocks for Building Bots\"><img src=\"/botkit_icon.png\" width=\"15\" height=\"15\" alt=\"Botkit Logo\" /> Botkit</a>\n            </div>\n            <section>\n                <div id=\"message_list\">\n                    <div id=\"message_template\">\n                        <div class=\"message {{message.type}}\">\n                            {{#if message.isTyping}}\n                              <div class=\"typing-indicator\">\n                                <span></span>\n                                <span></span>\n                                <span></span>\n                              </div>\n                            {{/if}}\n                            {{{message.html}}}\n\n                            {{#if message.open_link}}\n                              <a href=\"{{{message.open_link}}}\" target=\"_blank\" class=\"button_message\">{{#if message.link_title}}{{message.link_title}}{{else}}{{message.open_link}}{{/if}}</a>\n                            {{/if}}\n                        </div>\n                        {{#message.files}}\n                          <div class=\"file_attachment\">\n                          {{#if image}}\n                            <img src=\"{{{url}}}\" alt=\"{{{url}}}\" />\n                          {{else}}\n                            <a href=\"{{{url}}}\" title=\"{{{url}}}\">{{{url}}}</a>\n                          {{/if}}\n                          </div>\n                        {{/message.files}}\n                    </div>\n                </div>\n            </section>\n            <div id=\"message_replies\">\n            </div>\n            <footer>\n                <form onsubmit=\"Botkit.send(Botkit.input.value, event)\">\n                    <input type=\"text\" autocomplete=\"off\" id=\"messenger_input\" placeholder=\"Type here...\" />\n                    <button type=\"submit\">Send</button>\n                </form>\n            </footer>\n        </div>\n        </div>\n        <script src=\"/client.js\"></script>\n    </body>\n</html>\n"
  },
  {
    "path": "packages/botbuilder-adapter-web/client/readme.md",
    "content": "## Botkit's Customizable web-based chat client\n\nBotkit includes an easy to customize chat client that can be used as a full-screen web app, built into the structure\nof an existing page, or embedded in an entire site with an iframe.\n\nThe built-in client uses websocket or webhook connections to establish a real time connection\nto your Botkit app in order to instantly send and receive messages. It supports bot-friendly\nfeatures like quick replies and image attachments. It gracefully handles failed connections\nand reconnects.\n\nThe chat client is built with HTML, CSS and vanilla Javascript.\nDevelopers can customize the look and feel of the client by modifying the included markup and CSS.\nNew chat features such as custom cards or actions can be added with just a little bit of code.\n\n* [How to use typing indicators](#typing-indicators)\n* [How to embed a bot in your website](#embed-botkit-in-a-website-with-iframes)\n* [How to customize the look and feel of your web chat](#customize-the-look-and-feel-of-the-chat-interface)\n* [How to share user account/profile info with Botkit](#share-user-accounts--profile-data-with-botkit)\n\n\nThere are three ways to use the web client:\n\n1. [Embed the widget using an iFrame](#embed-botkit-in-a-website-with-iframes)\n2. Link directly to full-screen chat interface\n3. Embed the chat interface markup, css and Javascript into an existing web page\n\n### Files\n\nThe web chat client is composed of these files:\n\n* HTML user interface [index.html](index.html)\n* Javascript application [client.js](client.js)\n* Compiled CSS theme [css/styles.css](css/styles.css)\n* Source SASS file [sass/_chat.scss](sass/_chat.scss)\n\nAdditional functionality used by the iframe embed:\n\n* Embedded chat app [embed.js](embed.js)\n* Compiled CSS for embedded window [css/embed.css](css/embed.css)\n* Source SASS file [sass/embed.scss](sass/embed.scss)\n\n## Client API\n\n#### Botkit.boot(user)\n\nInitialize the embedded chat widget.  This will cause the widget to connect to the chat service and start up.\n\nIf your website has user accounts, and you want to identify the existing user to the chat widget,\nyou can include user profile information in the call to Botkit.boot(). \nThe user object can contain the following fields:\n\n| Field | Description\n|--- |---\n| id | REQUIRED a unique identifier of this user\n| name | the username / display name of the user\n| first_name | first name\n| last_name | last name\n| full_name | full name\n| gender | 'male' or 'female'\n| timezone | Timezone description \"America/Chicago\"\n\n#### Botkit.identifyUser(user)\n\nIdentify an existing user to the chat widget. This can be used to identify the user AFTER the chat begins, instead of passing in the information to Botkit.boot().\n\n## Share User Accounts / Profile data with Botkit\n\nIn order to seamlessly integrate your new bot with your existing app or website, Botkit supports sharing user account information between the main app and the bot.\n\nTo do this, either call [Botkit.boot(user)](#botkitbootuser) with the optional user profile parameter, or call [Botkit.identifyUser(user)](#botkitidentifyuseruser) after the connection has been established.\n\nIt is important to note that Botkit does not provide any mechanism for validating or verifying the identity of the user passed in via these mechanisms. Used without validation, users can potentially access content associated with other users. For this reason, we recommend that Botkit Anywhere not be used to handle sensitive or private information unless substantial security mechanisms are put in place.\n\n## Typing Indicators\n\nBotkit can send typing indicators to the client to indicate that work is happening behind the scenes.\n\nTo achieve this, send a message in the form: `{\"type\": \"typing\"}`\n\nThe typing indicator will appear until the next message arrives. Typing indicators can be added to dialogs to indicate activity during long running operations. If you wish to have a typing indicator appear before every message, use a middleware to send the indicator and then delay the actual message.\n\nFor some examples of this in use, [see the sample code here &raquo;](https://github.com/howdyai/botkit/blob/master/packages/testbot/features/websocket_features.js)\n\n## Embed Botkit in a Website with iFrames\n\nBotkit's web chat can be added to a website using an iframe to embed the chat functionality.\nThe starter kit application includes a page with the necessary embed code that can be copy-pasted into the source of your website.\n\nAn example embed code is below.  It includes the markup for an iframe, as well as Javascript and CSS links for\nstyling the embedded chat widget. Note, replace `{{base_url}}` with the url of your Botkit application.\n\n```html\n<div id=\"embedded_messenger\">\n    <header id=\"message_header\" onclick=\"Botkit.toggle()\">Chat</header>\n    <iframe  id=\"botkit_client\" src=\"//{{base_url}}/chat.html\"></iframe>\n</div>\n<script src=\"//{{base_url}}/embed.js\"></script>\n<script>\nvar options = {};\nBotkit.boot(options);\n</script>\n<link rel=\"stylesheet\" href=\"//{{base_url}}/embed.css\" />\n\n```\n\nOnce embedded, the chat widget has a few additional methods that allow you to control it from the main web page.\n\n#### Botkit.activate()\n\nActivate the chat widget. If using the built-in stylesheet, this will cause the widget to slide up from the bottom of the screen.\n\n#### Botkit.deactivate()\n\nDeactivate the chat widget. If using the built-in stylesheet, this will cause the widget to disappear, leaving only a small \"Chat\" widget docked to the bottom of the page.\n\n#### Botkit.toggle()\n\nToggle the active state of the chat widget.\n\n\n## Customize the look and feel of the chat interface\n\nThe web chat interface is built with HTML and CSS. The look and feel can be extensively customized by modifying the underlying source code. The chat interface is rendered using the [Handlebars template language](http://handlebarsjs.com/).\n\nThe uncompiled SASS used to style the web chat is included in the starter kit as `sass/_chat.scss` Changes made to this file must be compiled into the final stylesheet. To do this, run the following command from the root of the starter kit:\n\n```\nsass --update sass/:/css/\n```\n\nThe annotated boilerplate HTML for Botkit's web client is below.\n\nNote: The functionality of the web chat interface uses the `id` attributes of elements in the template to identify and use them. If you want to use the built in client app, it is important to leave these attributes intact in the template file!\n\n```html\n<!-- the client uses the Handlebars template library and the Showdown markdown renderer -->\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.10/handlebars.min.js\"></script>\n<script src=\"https://cdn.rawgit.com/showdownjs/showdown/1.7.4/dist/showdown.min.js\"></script>\n\n<!-- Include the styleshet -->\n<link rel=\"stylesheet\" href=\"css/styles.css\" />\n\n<!-- this is the template for Botkit's web client -->\n<div id=\"message_window\">\n    <!-- this bar will appear if the websocket connection is not established -->\n    <div class=\"disconnected\">\n        Disconnected... reconnecting!\n    </div>\n\n    <!-- this bar will appear if the websocket connection has failed to reconnect after a disconnect -->\n    <div class=\"offline\">\n        Offline! Reload to reconnect.\n    </div>\n\n    <!-- this section contains the scrolling list of messages -->\n    <section>\n        <div id=\"message_list\">\n\n            <!--\n              this div is used to format both incoming and outgoing messages.\n              they are styled differently based a css class tied to the message.type field\n            -->\n            <div id=\"message_template\">\n                <div class=\"message {{message.type}}\">\n                    {{#if message.isTyping}}\n                        <div class=\"typing-indicator\">\n                            ...\n                        </div>\n                    {{/if}}\n\n                    {{{message.html}}}\n\n                    <!-- If the open_link field is present in the message, insert a button -->\n                    {{#if message.open_link}}\n                      <a href=\"{{{message.open_link}}}\" target=\"_blank\" class=\"button_message\">{{#if message.link_title}}{{message.link_title}}{{else}}{{message.open_link}}{{/if}}</a>\n                    {{/if}}\n\n                    <!-- if the files field is present in the message, render links to attached files -->\n                    {{#message.files}}\n                      {{#if image}}\n                        <img src=\"{{{url}}}\" alt=\"{{{url}}}\" />\n                      {{else}}\n                        <a href=\"{{{url}}}\">{{{url}}}</a>\n                      {{/if}}\n                    {{/message.files}}\n                </div>\n            </div>\n        </div>\n    </section>\n\n    <!-- this element contains any quick replies -->\n    <div id=\"message_replies\">\n    </div>\n\n    <!-- the footer is contains the message composer, and is docked to the footer of the chat -->\n    <footer>\n        <form onsubmit=\"Botkit.send(Botkit.input.value, event)\">\n            <input type=\"text\" autocomplete=\"off\" id=\"messenger_input\" placeholder=\"Type here...\" />\n            <button type=\"submit\">Send</button>\n        </form>\n    </footer>\n</div>\n```\n\n## Using Botkit CMS custom fields to add custom features\n\nBotkit CMS's dialog authoring tool supports the ability to add custom fields to any message.\nThese fields are passed unmodified through the client to your chat widget, and can be used in the template.\n\nYou can include any fields you want in your message objects using this feature, and render them however you desire.  The Handlebars template system supports conditionals, iterators and other helper functions which can be used to create interactive elements and more complex attachments.\n\nFor example, the code above looks for a `message.open_link` field. This is not a standard Botkit\nmessage field, but can be added to a message using custom fields. If present, a special link button will be added to the rendered message.\n"
  },
  {
    "path": "packages/botbuilder-adapter-web/client/sass/_botkit.scss",
    "content": "$botkit_purple: #a795ef;\n@mixin clearfix {\n    &:after {\n        content: \"\";\n        display: table;\n        clear: both;\n    }\n}\n\n* {\n    box-sizing: border-box;\n}\n\nbody,\nhtml {\n    margin: 0;\n    padding: 0;\n    font-size: 18px;\n    background-color: #FFF;\n    font-family: 'helvetica', sans-serif;\n}\n\n.wrapper {\n    @include clearfix;\n    position: relative;\n    max-width: 1000px;\n    margin: 0 auto;\n}\n\n.box {\n    @include clearfix;\n    border: 2px solid #CCC;\n    padding: 1rem calc(1rem - 2px);\n    margin-bottom: 1rem;\n\n    h1,\n    h2,\n    h3 {\n        margin-top: 0;\n    }\n}\n\nfooter {\n    text-align: center;\n}\n\n.hero {\n    text-align: center;\n    padding: 2rem;\n\n    h1 {\n        font-size: 4rem;\n        margin: 0;\n\n    }\n}\n\na {\n    color: $botkit_purple;\n}\n\n.copyurl {\n    width: 100%;\n    font-size: 1.25rem;\n}\n\ndiv.input {\n    label {\n        font-weight: bold;\n        font-size: smaller;\n    }\n}\n\n.addon {\n    display: flex;\n    border: 1px solid #999;\n    border-radius: 6px;\n    padding: 5px;\n    background: #F0F0F0;\n\n    input,\n    textarea {\n        flex-grow: 1;\n        border: 0;\n        background: transparent;\n    }\n\n    button {\n        flex-grow: 0;\n        background: transparent;\n        border: 1px solid #999;\n        border-radius: 6px;\n        font-weight: bold;\n\n        &.textarea {\n            align-self: flex-start;\n            padding: 0.5rem;\n        }\n\n        &:hover {\n            background: #FFF;\n            color: $botkit_purple;\n        }\n    }\n}\n\ndiv.hr {\n    border: 1px dashed #ccc;\n    width: 10%;\n    margin: 4rem auto;\n    height: 1px;\n}\n\na.button {\n    border: 2px solid $botkit_purple;\n    font-weight: bold;\n    // font-size: 4rem;\n    margin: 0;\n    border-radius: 3px;\n    display: inline-block;\n    padding: 0.5rem 2rem;\n    text-align: center;\n    text-decoration: none;\n    // color: #FFF;\n    box-shadow: 5px 5px 5px rgba(0,0,0,0.2);\n    background-color: #FFF;\n    transition: box-shadow 0.1s linear;\n\n    &:hover {\n        // background-color: rgba($botkit_purple, 0.1);\n        box-shadow: 1px 1px 5px rgba(0,0,0,0.1);\n    }\n}\n"
  },
  {
    "path": "packages/botbuilder-adapter-web/client/sass/_chat.scss",
    "content": "$action_color: orange;\n$background: #FFFFFF;\n$bot_message_background: #F0F0F0;\n$bot_message_text: #333;\n$human_message_background: $botkit_purple;\n$human_message_text: white;\n\n#message_window {\n    background: $background;\n    border-left: 1px solid #CCC;\n    border-right: 1px solid #CCC;\n\n    /*height: 500px;\n    width: 320px;*/\n    height: 100%;\n    width: 100%;\n    /*margin: 2rem auto;*/\n    display: flex;\n    flex-direction: column;\n    font-family: 'helvetica', sans-serif;\n\n    .disconnected {\n        background: #FFFFCC;\n        padding: 0.25rem;\n    }\n    &.connected .disconnected {\n        display: none;\n    }\n    .offline {\n        display: none;\n    }\n    &.offline {\n\n      .disconnected {\n        display: none;\n      }\n      .offline {\n        background: #FF0000;\n        color: #FFF;\n        padding: 0.25rem;\n        display: block;\n      }\n    }\n\n    .powered_by {\n      flex-shrink: 0;\n      text-align: center;\n\n      border-bottom: 1px solid #CCC;\n      font-size: 14px;\n      padding: 0.25rem;\n      color: #666;\n\n      a {\n        text-decoration: none;\n        color: #666;\n      }\n\n      img {\n        position: relative;\n        top: 2px;\n      }\n    }\n\n   section {\n      flex-grow:  1;\n      flex-direction: column-reverse;\n      display: flex;\n      overflow-y: auto;\n\n     div div {\n        margin: 0.25rem;\n        clear: both;\n    }\n  }\n\n  footer {\n      border-top: 1px solid #CCC;\n      padding: 0.25rem;\n      input[type=\"text\"] {\n          flex-grow: 1;\n          font-size: 1.25rem;\n          outline: none;\n          border: none;\n      }\n      button {\n         width: 50px;\n         background: none;\n         border: 0;\n         cursor: pointer;\n         color: blue;\n         font-weight: bold;\n     }\n  }\n\n  form {\n      display: flex;\n      margin: 0;\n      padding: 0.25rem;\n  }\n\n  #message_template {\n      display: none;\n  }\n\n  .message {\n      font-size: 14px;\n      padding: 0.5rem;\n      background: $bot_message_background;\n      color: $bot_message_text;\n      border-radius: 5px;\n      width: auto;\n      display: inline-block;\n      max-width: 75%;\n\n  }\n\n  .file_attachment {\n\n    background: $bot_message_background;\n    color: $bot_message_text;\n    border-radius: 5px;\n    display: inline-block;\n    max-width: 75%;\n\n    img {\n      max-width: 100%;\n      display: block;\n    }\n\n  }\n\n    .button_message {\n      margin: 1rem 0;\n      border-radius: 4px;\n      border-color: $action_color;\n      border-style: solid;\n      color: $action_color;\n      border-width: 1px;\n      padding: 0.25rem 1rem;\n      text-decoration: none;\n      text-align: center;\n      box-shadow: 1px 1px 2px rgba(0,0,0,0.25);\n      display: block;\n    }\n\n\n  .message p {\n      margin-top: 0;\n      margin-bottom: 0.5rem;\n  }\n\n  .message p:last-child {\n      margin-bottom: 0;\n  }\n\n  .message.outgoing {\n      float: right;\n\n      background: $human_message_background;\n      color: $human_message_text;\n\n  }\n\n  #message_replies {\n      text-align: center;\n      overflow-x: auto;\n      flex-shrink: 0;\n      -webkit-overflow-scrolling: touch; /* Lets it scroll lazy */\n\n      ul {\n          list-style-type: none;\n          margin: 0px auto;\n          padding: 0;\n          li {\n              display: inline-block;\n              margin: 0.5rem;\n              margin-left: 0;\n          }\n      }\n\n      a {\n         text-decoration: none;\n         display: block;\n         border: 1px solid $botkit_purple;\n         color: $botkit_purple;\n         border-radius: 16px;\n         padding: 0.25rem 1rem;\n         font-size: 14px;\n         cursor: pointer;\n\n         &:hover {\n           background: $botkit_purple;\n           color: #FFF;\n         }\n     }\n   }\n}\n\n\n\n/* typing indicator CSS based on code by Joseph Fusco -> https://codepen.io/fusco/pen/XbpaYv */\n.typing-indicator {\n  display: table;\n  margin: 0 auto;\n  position: relative;\n  span {\n    height: 5px;\n    width: 5px;\n    float: left;\n    margin: 0 1px;\n    background-color: $bot_message_text;\n    display: block;\n    border-radius: 50%;\n    opacity: 0.4;\n    @for $i from 1 through 3 {\n      &:nth-of-type(#{$i}) {\n        animation: 1s blink infinite ($i * .3333s);\n      }\n    }\n  }\n}\n\n@keyframes blink {\n  50% {\n    opacity: 1;\n  }\n}\n"
  },
  {
    "path": "packages/botbuilder-adapter-web/client/sass/_home.scss",
    "content": "#home {\n    @include clearfix;\n    position: relative;\n    max-width: 650px;\n    margin: auto;\n}\n\n#homepage_bot {\n    width: 400px;\n    height: 450px;\n    float: left;\n    border: 5px solid #333;\n\n    iframe {\n        border: 0;\n        height: 100%;\n        width: 100%;\n    }\n    box-shadow: 5px 5px 5px rgba(0,0,0,0.5);\n}\n\n#welcome {\n    margin-left: 440px;\n}\n"
  },
  {
    "path": "packages/botbuilder-adapter-web/client/sass/embed.scss",
    "content": "$height: 400px;\n\n#embedded_messenger {\n\n  position: fixed;\n  z-index: 1000;\n\n  bottom: -$height;\n  right: 2rem;\n\n  height: $height + 34;\n  transition: 0.5s ease-in-out bottom;\n\n  &.active {\n    bottom: 0;\n  }\n\n  iframe {\n    height: $height;\n    width: 100%;\n    border: 0;\n  }\n\n  #message_header {\n    background: #000;\n    padding: 0.5rem 1rem;\n    color: #FFF;\n  }\n\n}\n"
  },
  {
    "path": "packages/botbuilder-adapter-web/client/sass/styles.scss",
    "content": "/* shared botkit ui styles */\n@import \"_botkit\";\n\n/* chat client */\n@import \"_chat\";\n\n/* special styles for homepage */\n@import \"_home\";\n"
  },
  {
    "path": "packages/botbuilder-adapter-web/package.json",
    "content": "{\n  \"name\": \"botbuilder-adapter-web\",\n  \"version\": \"1.0.10\",\n  \"description\": \"Connect Botkit or BotBuilder to the Web\",\n  \"main\": \"./lib/index.js\",\n  \"typings\": \"./lib/index.d.ts\",\n  \"files\": [\n    \"/lib\",\n    \"/src\",\n    \"/client\"\n  ],\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"test\": \"tsc ; nyc mocha tests/*.tests.js\",\n    \"eslint\": \"./node_modules/.bin/eslint --fix src/*\",\n    \"pack\": \"npm pack\"\n  },\n  \"author\": \"Microsoft Corp.\",\n  \"license\": \"MIT\",\n  \"keywords\": [\n    \"webchat\",\n    \"websocket\",\n    \"botkit\",\n    \"botbuilder\",\n    \"botframework\",\n    \"bots\",\n    \"chatbots\",\n    \"azure\"\n  ],\n  \"homepage\": \"https://github.com/howdyai/botkit/blob/master/packages/botbuilder-adapter-web#readme\",\n  \"bugs\": {\n    \"url\": \"https://github.com/howdyai/botkit/issues\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/howdyai/botkit.git\"\n  },\n  \"dependencies\": {\n    \"botkit\": \"^4.15.0\",\n    \"botbuilder\": \"^4.15.0\",\n    \"debug\": \"^4.1.0\",\n    \"url\": \"^0.11.0\",\n    \"ws\": \"^7.3.1\"\n  },\n  \"devDependencies\": {\n    \"eslint\": \"^8.3.0\",\n    \"eslint-config-standard\": \"^16.0.3\",\n    \"eslint-plugin-import\": \"^2.25.3\",\n    \"eslint-plugin-node\": \"^11.1.0\",\n    \"eslint-plugin-promise\": \"^5.1.1\",\n    \"eslint-plugin-standard\": \"^4.0.1\"\n  }\n}\n"
  },
  {
    "path": "packages/botbuilder-adapter-web/readme.md",
    "content": "# botbuilder-adapter-web\nConnect [Botkit](https://www.npmjs.com/package/botkit) or [BotBuilder](https://www.npmjs.com/package/botbuilder) to the Web.\n\nThis package contains an adapter that communicates directly with the web via webhooks or websocket connections.\nThis package can be used alongside your favorite bot development framework to build bots that work on a website or within an existing app.\n\n## Install Package\n\nAdd this package to your project using npm:\n\n```bash\nnpm install --save botbuilder-adapter-web\n```\n\nImport the adapter class into your code:\n\n```javascript\nconst { WebAdapter } = require('botbuilder-adapter-web');\n```\n\n## Get Started\n\nIf you are starting a brand new project, [follow these instructions to create a customized application template.](../docs/index.md)\n\n## Use WebAdapter in your App\n\nWebAdapter provides a translation layer for Botkit and BotBuilder so that bot developers can connect directly to users on the web.\n\n### Botkit Basics\n\nWhen used in concert with Botkit, developers need only pass the configured adapter to the Botkit constructor, as seen below. Botkit will automatically create and configure the webhook endpoints and other options necessary for communicating with the web.\n\nDevelopers can then bind to Botkit's event emitting system using `controller.on` and `controller.hears` to filter and handle incoming events from the messaging platform. [Learn more about Botkit's core feature &rarr;](../docs/index.md).\n\n[A full description of the WebAdapter options and example code can be found in the class reference docs.](../docs/reference/web.md#create-a-new-webadapter)\n\n```javascript\nconst adapter = new WebAdapter();\nconst controller = new Botkit({\n    adapter,\n    // ...other options\n});\n\n// TODO: expose chat client\n\ncontroller.on('message', async(bot, message) => {\n    await bot.reply(message, 'I heard a message!');\n});\n```\n\n### BotBuilder Basics\n\nAlternately, developers may choose to use `WebAdapter` with BotBuilder. With BotBuilder, the adapter is used more directly with a webserver, and all incoming events are handled as [Activities](https://docs.microsoft.com/en-us/javascript/api/botframework-schema/activity?view=botbuilder-ts-latest).\n\n[Read more &rarr;](../docs/reference/web.md#create-a-new-webadapter)\n\n## Class Reference\n\n* [WebAdapter](../docs/reference/web.md#webadapter)\n\n## Reference Chat Client\n\nThis package includes [a reference implementation of a chat client written in HTML/JS/CSS](https://github.com/howdyai/botkit/tree/master/packages/botbuilder-adapter-web/client/#readme) that serves as a base for building a customized chat widget.\n\n> [Using typing indicators with the reference chat client](https://github.com/howdyai/botkit/tree/master/packages/botbuilder-adapter-web/client/#typing-indicators)\n\n## Event List\n\n| Event | Description\n|--- |---\n| message | a message sent by the user\n| hello | event sent when a user first connects\n| welcome_back | event sent when a user reconnects\n| identify | an extended user profile is being sent by the client to be associated with the user id\n\n## Botkit Extensions\n\nIn Botkit handlers, the `bot` worker for web contains [all of the base methods](../docs/reference/core.md) as well as the following platform-specific extensions:\n\n### [adapter.createSocketServer()](../docs/reference/web.md#createsocketserver)\n\nConfigures the webserver to accept websocket connections. This method is called automatically by Botkit, but must be manually called when using with BotBuilder.\n\n## Community & Support\n\nJoin our thriving community of Botkit developers and bot enthusiasts at large.\nOver 10,000 members strong, [our Github site](https://github.com/howdyai/botkit) is\n_the place_ for people interested in the art and science of making bots.\nCome to ask questions, share your progress, and commune with your peers!\n\nYou can also find help from members of the Botkit team [in our dedicated Cisco Spark room](https://eurl.io/#SyNZuomKx)!\n\n## About Botkit\n\nBotkit is a part of the [Microsoft Bot Framework](https://dev.botframework.com).\n\nWant to contribute? [Read the contributor guide](https://github.com/howdyai/botkit/blob/master/CONTRIBUTING.md)\n\nBotkit is released under the [MIT Open Source license](https://github.com/howdyai/botkit/blob/master/LICENSE.md)\n"
  },
  {
    "path": "packages/botbuilder-adapter-web/src/index.ts",
    "content": "/**\n * @module botbuilder-adapter-web\n */\n/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport * from './web_adapter';\n"
  },
  {
    "path": "packages/botbuilder-adapter-web/src/web_adapter.ts",
    "content": "/**\n * @module botbuilder-adapter-web\n */\n/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { Activity, ActivityTypes, BotAdapter, ConversationReference, TurnContext, ResourceResponse } from 'botbuilder';\nimport * as Debug from 'debug';\nimport * as WebSocket from 'ws';\nconst debug = Debug('botkit:web');\n\nconst clients = {};\n\n/**\n * Connect [Botkit](https://www.npmjs.com/package/botkit) or [BotBuilder](https://www.npmjs.com/package/botbuilder) to the Web.\n * It offers both websocket and webhook capabilities.\n * To use this adapter, you will need a compatible chat client - generate one using the [Botkit yeoman generator](https://npmjs.com/package/generator-botkit),\n * or use [the one included in the project repo here.](https://github.com/howdyai/botkit/tree/master/packages/botbuilder-adapter-web/client)\n */\nexport class WebAdapter extends BotAdapter {\n    /**\n     * Name used to register this adapter with Botkit.\n     * @ignore\n     */\n    public name = 'Web Adapter';\n\n    /**\n     * The websocket server.\n     */\n    public wss;\n\n    private socketServerOptions: {\n        [key: string]: any;\n    };\n\n    /**\n     * Create an adapter to handle incoming messages from a websocket and/or webhook and translate them into a standard format for processing by your bot.\n     *\n     * To use with Botkit:\n     * ```javascript\n     * const adapter = new WebAdapter();\n     * const controller = new Botkit({\n     *      adapter: adapter,\n     *      // other options\n     * });\n     * ```\n     *\n     * To use with BotBuilder:\n     * ```javascript\n     * const adapter = new WebAdapter();\n     * const server = restify.createServer();\n     * server.use(restify.plugins.bodyParser());\n     * // instead of binding processActivity to the incoming request, pass in turn handler logic to createSocketServer\n     * let options = {}; // socket server configuration options\n     * adapter.createSocketServer(server, options, async(context) => {\n     *  // handle turn here\n     * });\n     * ```\n     *\n     * @param socketServerOptions an optional object containing parameters to send to a call to [WebSocket.server](https://github.com/websockets/ws/blob/master/doc/ws.md#new-websocketserveroptions-callback).\n     */\n    public constructor(socketServerOptions?: {[key: string]: any}) {\n        super();\n        this.socketServerOptions = socketServerOptions || null;\n    }\n\n    /**\n     * Botkit-only: Initialization function called automatically when used with Botkit.\n     *      * Calls createSocketServer to bind a websocket listener to Botkit's pre-existing webserver.\n     * @param botkit\n     */\n    public init(botkit): void {\n        // when the bot is ready, register the webhook subscription with the Webex API\n        botkit.ready(() => {\n            this.createSocketServer(botkit.http, this.socketServerOptions, botkit.handleTurn.bind(botkit));\n        });\n    }\n\n    /**\n     * Bind a websocket listener to an existing webserver object.\n     * Note: Create the server using Node's http.createServer\n     * @param server an http server\n     * @param socketOptions additional options passed when creating the websocket server with [WebSocket.server](https://github.com/websockets/ws/blob/master/doc/ws.md#new-websocketserveroptions-callback)\n     * @param logic a turn handler function in the form `async(context)=>{ ... }` that will handle the bot's logic.\n     */\n    public createSocketServer(server, socketOptions: any = {}, logic): void {\n        this.wss = new WebSocket.Server({\n            server,\n            ...socketOptions\n        });\n\n        function heartbeat(): void {\n            this.isAlive = true;\n        }\n\n        this.wss.on('connection', (ws) => {\n            ws.isAlive = true;\n            ws.on('pong', heartbeat);\n\n            ws.on('message', (payload) => {\n                try {\n                    const message = JSON.parse(payload);\n\n                    // note the websocket connection for this user\n                    ws.user = message.user;\n                    clients[message.user] = ws;\n\n                    // this stuff normally lives inside Botkit.congfigureWebhookEndpoint\n                    const activity = {\n                        timestamp: new Date(),\n                        channelId: 'websocket',\n                        conversation: {\n                            id: message.user\n                        },\n                        from: {\n                            id: message.user\n                        },\n                        recipient: {\n                            id: 'bot'\n                        },\n                        channelData: message,\n                        text: message.text,\n                        type: message.type === 'message' ? ActivityTypes.Message : ActivityTypes.Event\n                    };\n\n                    // set botkit's event type\n                    if (activity.type !== ActivityTypes.Message) {\n                        activity.channelData.botkitEventType = message.type;\n                    }\n\n                    const context = new TurnContext(this, activity as Activity);\n                    this.runMiddleware(context, logic)\n                        .catch((err) => { console.error(err.toString()); });\n                } catch (e) {\n                    const alert = [\n                        'Error parsing incoming message from websocket.'\n                    ];\n                    console.error(alert.join('\\n'));\n                    console.error(e);\n                }\n            });\n\n            ws.on('error', (err) => console.error('Websocket Error: ', err));\n\n            ws.on('close', function() {\n                delete (clients[ws.user]);\n            });\n        });\n\n        setInterval(() => {\n            this.wss.clients.forEach(function each(ws) {\n                if (ws.isAlive === false) {\n                    return ws.terminate();\n                }\n                ws.isAlive = false;\n                ws.ping('', false, () => {\n                    // noop\n                });\n            });\n        }, 30000);\n    }\n\n    /**\n     * Caste a message to the simple format used by the websocket client\n     * @param activity\n     * @returns a message ready to send back to the websocket client.\n     */\n    private activityToMessage(activity: Partial<Activity>): any {\n        const message = {\n            type: activity.type,\n            text: activity.text\n        };\n\n        // if channelData is specified, overwrite any fields in message object\n        if (activity.channelData) {\n            Object.keys(activity.channelData).forEach(function(key) {\n                message[key] = activity.channelData[key];\n            });\n        }\n\n        debug('OUTGOING > ', message);\n        return message;\n    }\n\n    /**\n     * Standard BotBuilder adapter method to send a message from the bot to the messaging API.\n     * [BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#sendactivities).\n     * @param context A TurnContext representing the current incoming message and environment. (not used)\n     * @param activities An array of outgoing activities to be sent back to the messaging API.\n     */\n    public async sendActivities(context: TurnContext, activities: Partial<Activity>[]): Promise<ResourceResponse[]> {\n        const responses = [];\n        for (let a = 0; a < activities.length; a++) {\n            const activity = activities[a];\n\n            const message = this.activityToMessage(activity);\n\n            const channel = context.activity.channelId;\n\n            if (channel === 'websocket') {\n                // If this turn originated with a websocket message, respond via websocket\n                const ws = clients[activity.recipient.id];\n                if (ws && ws.readyState === 1) {\n                    try {\n                        ws.send(JSON.stringify(message));\n                    } catch (err) {\n                        console.error(err);\n                    }\n                } else {\n                    console.error('Could not send message, no open websocket found');\n                }\n            } else if (channel === 'webhook') {\n                // if this turn originated with a webhook event, enqueue the response to be sent via the http response\n                let outbound = context.turnState.get('httpBody');\n                if (!outbound) {\n                    outbound = [];\n                }\n                outbound.push(message);\n                context.turnState.set('httpBody', outbound);\n            }\n        }\n\n        return responses;\n    }\n\n    /**\n     * Web adapter does not support updateActivity.\n     * @ignore\n     */\n    // eslint-disable-next-line\n     public async updateActivity(context: TurnContext, activity: Partial<Activity>): Promise<void> {\n        debug('Web adapter does not support updateActivity.');\n    }\n\n    /**\n     * Web adapter does not support updateActivity.\n     * @ignore\n     */\n    // eslint-disable-next-line\n     public async deleteActivity(context: TurnContext, reference: Partial<ConversationReference>): Promise<void> {\n        debug('Web adapter does not support deleteActivity.');\n    }\n\n    /**\n     * Standard BotBuilder adapter method for continuing an existing conversation based on a conversation reference.\n     * [BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#continueconversation)\n     * @param reference A conversation reference to be applied to future messages.\n     * @param logic A bot logic function that will perform continuing action in the form `async(context) => { ... }`\n     */\n    public async continueConversation(reference: Partial<ConversationReference>, logic: (context: TurnContext) => Promise<void>): Promise<void> {\n        const request = TurnContext.applyConversationReference(\n            { type: 'event', name: 'continueConversation' },\n            reference,\n            true\n        );\n        const context = new TurnContext(this, request);\n        return this.runMiddleware(context, logic)\n            .catch((err) => { console.error(err.toString()); });\n    }\n\n    /**\n     * Accept an incoming webhook request and convert it into a TurnContext which can be processed by the bot's logic.\n     * @param req A request object from Restify or Express\n     * @param res A response object from Restify or Express\n     * @param logic A bot logic function in the form `async(context) => { ... }`\n     */\n    public async processActivity(req, res, logic: (context: TurnContext) => Promise<void>): Promise<void> {\n        const message = req.body;\n\n        const activity = {\n            timestamp: new Date(),\n            channelId: 'webhook',\n            conversation: {\n                id: message.user\n            },\n            from: {\n                id: message.user\n            },\n            recipient: {\n                id: 'bot'\n            },\n            channelData: message,\n            text: message.text,\n            type: message.type === 'message' ? ActivityTypes.Message : ActivityTypes.Event\n        };\n\n        // set botkit's event type\n        if (activity.type !== ActivityTypes.Message) {\n            activity.channelData.botkitEventType = message.type;\n        }\n\n        // create a conversation reference\n        const context = new TurnContext(this, activity as Activity);\n\n        context.turnState.set('httpStatus', 200);\n\n        await this.runMiddleware(context, logic);\n\n        // send http response back\n        res.status(context.turnState.get('httpStatus'));\n        if (context.turnState.get('httpBody')) {\n            res.json(context.turnState.get('httpBody'));\n        } else {\n            res.end();\n        }\n    }\n\n    /**\n     * Is given user currently connected? Use this to test the websocket connection\n     * between the bot and a given user before sending messages,\n     * particularly in cases where a long period of time may have passed.\n     *\n     * Example: `bot.controller.adapter.isConnected(message.user)`\n     * @param user the id of a user, typically from `message.user`\n     */\n    public isConnected(user: string): boolean {\n        return typeof clients[user] !== 'undefined';\n    }\n\n    /**\n     * Returns websocket connection of given user\n     * Example: `if (message.action === 'disconnect') bot.controller.adapter.getConnection(message.user).terminate()`\n     * @param user\n     */\n    public getConnection(user: string): WebSocket {\n        if (!this.isConnected(user)) {\n            throw new Error('User ' + user + ' is not connected');\n        }\n        return clients[user];\n    }\n}\n"
  },
  {
    "path": "packages/botbuilder-adapter-web/tests/WebAdapter.tests.js",
    "content": "const assert = require('assert');\nconst { WebAdapter } = require('../');\n\ndescribe('WebAdapter', function() {\n\n    let adapter;\n\n    beforeEach(function () {\n        adapter = new WebAdapter({\n        });\n    });\n\n    it('should contruct without any parameters (none are required)', function () {\n        assert.doesNotThrow(function () { let adapter = new WebAdapter({}); }, 'Foo');\n    });\n\n    it('should create a WebAdapter object', function () {\n        assert((adapter instanceof WebAdapter), 'Adapter is wrong type');\n    });\n\n});\n"
  },
  {
    "path": "packages/botbuilder-adapter-web/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2015\",\n    \"module\": \"commonjs\",\n    \"declaration\": true,\n    \"sourceMap\": true,\n    \"outDir\": \"./lib\",\n    \"rootDir\": \"./src\",\n    \"types\" : [\"node\"],\n    \"lib\": [\n      \"es5\",\n      \"es2015\",\n      \"es2016.array.include\",\n      \"esnext.asynciterable\",\n      \"dom\"\n    ]\n  },\n  \"include\": [\n    \"src/**/*\"\n  ]\n}"
  },
  {
    "path": "packages/botbuilder-adapter-webex/.eslintrc.js",
    "content": "module.exports = {\n    \"extends\": \"standard\",\n    \"rules\": {\n        \"semi\": [2, \"always\"],\n        \"indent\": [2, 4],\n        \"no-return-await\": 0,\n        \"camelcase\": 0,\n        \"no-unused-vars\": 0,\n        \"@typescript-eslint/ban-ts-ignore\": 1,\n        \"@typescript-eslint/no-object-literal-type-assertion\": 0,\n        \"@typescript-eslint/indent\": 0,\n        \"@typescript-eslint/explicit-member-accessibility\": 1,\n        \"space-before-function-paren\": [2, {\n            \"named\": \"never\",\n            \"anonymous\": \"never\",\n            \"asyncArrow\": \"always\"\n        }],\n        \"template-curly-spacing\": [2, \"always\"]\n    }\n};"
  },
  {
    "path": "packages/botbuilder-adapter-webex/.gitignore",
    "content": ".nyc_output/\nnode_modules/\n.env\nlib/"
  },
  {
    "path": "packages/botbuilder-adapter-webex/CHANGELOG.md",
    "content": "# botbuilder-adapter-webex changelog\n\n# 1.0.9\n\n* Test for presence of channelData before accessing it. Thanks [@viveksyngh](https://github.com/viveksyngh) for the [pull request](https://github.com/howdyai/botkit/pull/2010)\n\n* Update dependencies to Botkit 4.10, Bot Framework 4.10\n\n\n\n# 1.0.8\n\n* Update dependencies to Botkit 4.9, Bot Framework 4.9\n* New: Add abilbity to start conversations or reply in a thread. Thanks to [@billyzoellers](https://github.com/billyzoellers) for the [pull request](https://github.com/howdyai/botkit/pull/1942)\n\n# 1.0.6\n\n* Fix issue where empty files field would cause issues. Thanks to [@viveksyngh](https://github.com/viveksyngh) - [PR #1906](https://github.com/howdyai/botkit/pull/1906)\n* Update to latest Webex API client library.\n\n\n# 1.0.5\n\n* Update to latest Webex API client library.\n* Fix to mention stripping to better support Webex web client formatting\n* Update dependencies (Bot Framework to 4.6, Botkit to 4.6)\n\n# 1.0.3\n\n* Add support for [Adaptive Cards](https://developer.webex.com/blog/new-buttons-cards-webex-teams) thanks to [@darrenparkinson](https://github.com/howdyai/botkit/pull/1760)\n* Replace `ciscospark` package with `webex` package, thanks to [@teamup](https://github.com/howdyai/botkit/pull/1748)\n\nDevelopers who wish to use this brand new feature should add the following lines to their bot.js file\nin order to create a dedicated webhook for receiving card submissions from the Webex client. Note that this\nis necessary due to a bug in the Webex webhook service, and will be removed from future versions.\n\n```\ncontroller.ready(async function() {\n    await controller.adapter.registerAdaptiveCardWebhookSubscription('/api/messages');\n});\n```\n\nOnce enabled, your bot will receive `attachmentActions` events with `message.inputs` set to include values from the card.\n\n# 1.0.2\n\n* Update dependencies (Bot Framework to 4.5.2, Botkit to 4.5)\n* Fix for file attachments\n\n# 1.0.1\n\n* 1:1 messages between bot and user will now emit `direct_message` events instead of `message` events\n* Messages will now have `orgId`, `appId` and `actorId` fields\n* Add `enable_incomplete` option to allow adapter to start without a complete config.\n\n# 1.0.0 \n\nFirst release\n"
  },
  {
    "path": "packages/botbuilder-adapter-webex/LICENSE.md",
    "content": "Copyright XOXCO, Inc, http://xoxco.com, http://howdy.ai\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "packages/botbuilder-adapter-webex/package.json",
    "content": "{\n  \"name\": \"botbuilder-adapter-webex\",\n  \"version\": \"1.0.10\",\n  \"description\": \"Connect Botkit or BotBuilder to Webex Teams\",\n  \"main\": \"./lib/index.js\",\n  \"typings\": \"./lib/index.d.ts\",\n  \"files\": [\n    \"/lib\",\n    \"/src\"\n  ],\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"test\": \"tsc ; nyc mocha tests/*.tests.js\",\n    \"eslint\": \"./node_modules/.bin/eslint --fix src/*\",\n    \"pack\": \"npm pack\"\n  },\n  \"author\": \"Microsoft Corp.\",\n  \"license\": \"MIT\",\n  \"keywords\": [\n    \"webex\",\n    \"botkit\",\n    \"botbuilder\",\n    \"botframework\",\n    \"bots\",\n    \"chatbots\",\n    \"azure\"\n  ],\n  \"homepage\": \"https://github.com/howdyai/botkit/blob/master/packages/botbuilder-adapter-webex#readme\",\n  \"bugs\": {\n    \"url\": \"https://github.com/howdyai/botkit/issues\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/howdyai/botkit.git\"\n  },\n  \"dependencies\": {\n    \"botbuilder\": \"^4.15.0\",\n    \"botkit\": \"^4.15.0\",\n    \"debug\": \"^4.1.0\",\n    \"url\": \"^0.11.0\",\n    \"webex\": \"^1.80.148\"\n  },\n  \"devDependencies\": {\n    \"eslint\": \"^8.3.0\",\n    \"eslint-config-standard\": \"^16.0.3\",\n    \"eslint-plugin-import\": \"^2.25.3\",\n    \"eslint-plugin-node\": \"^11.1.0\",\n    \"eslint-plugin-promise\": \"^5.1.1\",\n    \"eslint-plugin-standard\": \"^4.0.1\"\n  }\n}\n"
  },
  {
    "path": "packages/botbuilder-adapter-webex/readme.md",
    "content": "# botbuilder-adapter-webex\nConnect [Botkit](https://www.npmjs.com/package/botkit) or [BotBuilder](https://www.npmjs.com/package/botbuilder) to Webex Teams.\n\nThis package contains an adapter that communicates directly with the Webex Teams API,\nand translates messages to and from a standard format used by your bot. This package can be used alongside your favorite bot development framework to build bots that work with Webex Teams.\n\n## Install Package\n\nAdd this package to your project using npm:\n\n```bash\nnpm install --save botbuilder-adapter-webex\n```\n\nImport the adapter class into your code:\n\n```javascript\nconst { WebexAdapter } = require('botbuilder-adapter-webex');\n```\n\n## Get Started\n\nIf you are starting a brand new project, [follow these instructions to create a customized application template.](../docs/index.md)\n\n## Use WebexAdapter in your App\n\nWebexAdapter provides a translation layer for Botkit and BotBuilder so that bot developers can connect to Webex Teams and have access to Webex's API.\n\n### Botkit Basics\n\nWhen used in concert with Botkit, developers need only pass the configured adapter to the Botkit constructor, as seen below. Botkit will automatically create and configure the webhook endpoints and other options necessary for communicating with Webex.\n\nDevelopers can then bind to Botkit's event emitting system using `controller.on` and `controller.hears` to filter and handle incoming events from the messaging platform. [Learn more about Botkit's core feature &rarr;](../docs/index.md).\n\n[A full description of the WebexAdapter options and example code can be found in the class reference docs.](../docs/reference/webex.md#create-a-new-webexadapter)\n\n```javascript\nconst adapter = new WebexAdapter({\n    access_token: process.env.ACCESS_TOKEN,\n    public_address: process.env.PUBLIC_ADDRESS,\n    secret: process.env.SECRET \n});\n\nconst controller = new Botkit({\n    adapter,\n    // ...other options\n});\n\ncontroller.on('message', async(bot, message) => {\n    await bot.reply(message, 'I heard a message!');\n});\n```\n\n### BotBuilder Basics\n\nAlternately, developers may choose to use `WebexAdapter` with BotBuilder. With BotBuilder, the adapter is used more directly with a webserver, and all incoming events are handled as [Activities](https://docs.microsoft.com/en-us/javascript/api/botframework-schema/activity?view=botbuilder-ts-latest).\n\n```javascript\nconst adapter = new WebexAdapter({\n    access_token: process.env.ACCESS_TOKEN,\n    public_address: process.env.PUBLIC_ADDRESS,\n    secret: process.env.SECRET \n});\n\nconst server = restify.createServer();\nserver.use(restify.plugins.bodyParser());\nserver.post('/api/messages', (req, res) => {\n     adapter.processActivity(req, res, async(context) => {\n         await context.sendActivity('I heard a message!');\n     });\n});\n```\n\n## Class Reference\n\n* [WebexAdapter](../docs/reference/webex.md#webexadapter)\n* [BotWorker Extensions](../docs/reference/webex.md#webexbotworker)\n\n## Event List\n\nAll events [listed here](https://developer.webex.com/webhooks-explained.html#resources-events) should be expected, in the format `resource`.`event` - for example, `rooms.created`.  \n\n| Event | Description\n|--- |---\n| message |\n| self_message | \n\n\n## Calling Webex APIs\n\nThis package exposes a pre-configured [Webex API client](https://www.npmjs.com/package/webex) for developers who want to use one of the many available API endpoints.\n\nIn Botkit handlers, the `bot` worker object passed into all handlers will contain a `bot.api` field that contains the client, preconfigured and ready to use.\n\n```javascript\ncontroller.on('message', async(bot, message) {\n\n    // get a list of the members of a room\n    let members = await bot.api.memberships.get(message.channel);\n    // .. do stuff\n});\n```\n\n## Botkit Extensions\nIn Botkit handlers, the `bot` worker for Webex contains [all of the base methods](../docs/reference/core.md#BotWorker) as well as the following platform-specific extensions:\n\n### [bot.startConversationInRoom()](../docs/reference/webex.md#startconversationinroom)\n\nUse this method to initiate a conversation with a user in a given, known room.  After calling this method, any further actions carried out by the bot worker will happen in that context.\n\nThis can be used to create or resume conversations with users that are not in direct response to an incoming message, like those sent on a schedule or in response to external events.\n\n### [bot.startPrivateConversation()](../docs/reference/webex.md#startprivateconversation)\n\nUse this method to initiate a private 1:1 conversation with a user.\n\nCalling this method will create or switch to the private 1:1 room for any messages sent with `bot.say`. However, due to a quirk in the Webex protocol, multi-message dialogs started with `beginDialog` will not work.\n\n### Remove messages\n\nWebex Teams supports deleting messages. Do so with the following convenience method:\n\n* [bot.deleteMessage](../docs/reference/webex.md#deletemessage)\n\n## Community & Support\n\nJoin our thriving community of Botkit developers and bot enthusiasts at large.\nOver 10,000 members strong, [our open Slack group](https://community.botkit.ai) is\n_the place_ for people interested in the art and science of making bots.\nCome to ask questions, share your progress, and commune with your peers!\n\nYou can also find help from members of the Botkit team [in our dedicated Cisco Spark room](https://eurl.io/#SyNZuomKx)!\n\n## About Botkit\n\nBotkit is a part of the [Microsoft Bot Framework](https://dev.botframework.com).\n\nWant to contribute? [Read the contributor guide](https://github.com/howdyai/botkit/blob/master/CONTRIBUTING.md)\n\nBotkit is released under the [MIT Open Source license](https://github.com/howdyai/botkit/blob/master/LICENSE.md)\n"
  },
  {
    "path": "packages/botbuilder-adapter-webex/src/botworker.ts",
    "content": "/**\n * @module botbuilder-adapter-webex\n */\n/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { BotWorker, BotkitMessage } from 'botkit';\nimport * as Webex from 'webex';\n\n/**\n * This is a specialized version of [Botkit's core BotWorker class](core.md#BotWorker) that includes additional methods for interacting with Webex Teams.\n * It includes all functionality from the base class, as well as the extension methods below.\n *\n * When using the WebexAdapter with Botkit, all `bot` objects passed to handler functions will include these extensions.\n */\nexport class WebexBotWorker extends BotWorker {\n    /**\n     * An instance of the [webex api client](https://www.npmjs.com/package/webex)\n     */\n    public api: Webex;\n\n    /**\n     * Change the context of the _next_ message\n     * Due to a quirk in the Webex API, we can't know the address of the DM until after sending the first message.\n     * As a result, the internal tracking for this conversation can't be persisted properly.\n     * USE WITH CAUTION while we try to sort this out.\n     * @param userId user id of a webex teams user, like one from `message.user`\n     */\n    public async startPrivateConversation(userId: string): Promise<any> {\n        // send a message with the toPersonId or toPersonEmail set\n        // response will have the roomID\n        return this.changeContext({\n            from: { id: userId },\n            // @ts-ignore\n            conversation: { id: 'temporary-value' }, // TODO: this is fake\n            channelId: 'webex'\n        });\n    };\n\n    /**\n     * Switch a bot's context into a different room.\n     * After calling this method, messages sent with `bot.say` and any dialogs started with `bot.beginDialog` will occur in this new context.\n     *\n     * ```javascript\n     * controller.hears('take this offline', 'message', async(bot, message) => {\n     *\n     *      // switch to a different channel\n     *      await bot.startConversationInRoom(WEBEX_ROOM_ID, message.user);\n     *\n     *      // say hello\n     *      await bot.say('Shall we discuss this matter over here?');\n     *      // ... continue...\n     *      await bot.beginDialog(ANOTHER_DIALOG);\n     *\n     * });\n     * ```\n     *\n     * Also useful when sending pro-active messages such as those sent on a schedule or in response to external events:\n     * ```javascript\n     * // Spawn a worker\n     * let bot = await controller.spawn();\n     *\n     * // Set the context for the bot's next action...\n     * await bot.startConversationInRoom(CACHED_ROOM_ID, CACHED_USER_ID);\n     *\n     * // Begin a dialog in the 1:1 context\n     * await bot.beginDialog(ALERT_DIALOG);\n     * ```\n     *\n     * @param roomId A Webex rooom id, like one found in `message.channel`\n     * @param userId A Webex user id, like one found in `message.user`\n     */\n    public async startConversationInRoom(roomId: string, userId: string): Promise<any> {\n        return this.changeContext({\n            // @ts-ignore ignore warning about missing optional fields\n            conversation: {\n                id: roomId\n            },\n            user: { id: userId, name: null },\n            channelId: 'webex'\n        });\n    }\n\n    /**\n     * Switch a bot's context into a specific thread within a room.\n     * After calling this method, messages sent with `bot.say` and any dialogs started with `bot.beginDialog` will occur in this new context.\n     *\n     * ```javascript\n     * controller.hears('take this offline', 'message', async(bot, message) => {\n     *\n     *      // switch to a different channel\n     *      await bot.startConversationInThread(WEBEX_ROOM_ID, message.user, message.id);\n     *\n     *      // say hello\n     *      await bot.say('Shall we discuss this matter over here?');\n     *      // ... continue...\n     *      await bot.beginDialog(ANOTHER_DIALOG);\n     *\n     * });\n     * ```\n     *\n     * Also useful when sending pro-active messages such as those sent on a schedule or in response to external events:\n     * ```javascript\n     * // Spawn a worker\n     * let bot = await controller.spawn();\n     *\n     * // Set the context for the bot's next action...\n     * await bot.startConversationInRoom(CACHED_ROOM_ID, CACHED_USER_ID);\n     *\n     * // Begin a dialog in the 1:1 context\n     * await bot.beginDialog(ALERT_DIALOG);\n     * ```\n     *\n     * @param roomId A Webex rooom id, like one found in `message.channel`\n     * @param userId A Webex user id, like one found in `message.user`\n     * @param parentId A webex message id that should be the parent message, like the one found in `message.id`\n     */\n    public async startConversationInThread(roomId: string, userId: string, parentId: string): Promise<any> {\n        return this.changeContext({\n            // @ts-ignore ignore warning about missing optional fields\n            conversation: {\n                id: roomId,\n                // @ts-ignore this field is required for webex\n                parentId: parentId\n            },\n            user: { id: userId, name: null },\n            channelId: 'webex'\n        });\n    }\n\n    /**\n     * Like bot.reply, but as a threaded response to the incoming message rather than a new message in the main channel.\n     * @param src an incoming message object\n     * @param resp an outgoing message object (or part of one or just reply text)\n     */\n    public async replyInThread(src: any, resp: any): Promise<any> {\n        // set parentId to src.id\n        resp.parentId = src.parentId ? src.parentId : src.id;\n        return this.reply(src, resp);\n    }\n\n    /**\n     * Delete an existing message.\n     *\n     * ```javascript\n     * // send a reply, capture the results\n     * let sent = await bot.reply(message,'this is my original reply...');\n     *\n     * // delete the sent message using the sent.id field\n     * await bot.deleteMessage(sent);\n     * ```\n     *\n     * @param update An object in the form of `{id: <id of message to delete>}`\n     */\n    public async deleteMessage(update: Partial<BotkitMessage>): Promise<any> {\n        return this.controller.adapter.deleteActivity(\n            this.getConfig('context'), // not currently used\n            {\n                activityId: update.id\n            }\n        );\n    }\n}\n"
  },
  {
    "path": "packages/botbuilder-adapter-webex/src/index.ts",
    "content": "/**\n * @module botbuilder-adapter-webex\n */\n/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport * from './webex_adapter';\nexport * from './botworker';\n"
  },
  {
    "path": "packages/botbuilder-adapter-webex/src/webex_adapter.ts",
    "content": "/**\n * @module botbuilder-adapter-webex\n */\n/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { Activity, ActivityTypes, BotAdapter, ResourceResponse, ConversationReference, TurnContext } from 'botbuilder';\nimport { WebexBotWorker } from './botworker';\nimport * as Webex from 'webex';\nimport * as url from 'url';\nimport * as crypto from 'crypto';\nimport * as Debug from 'debug';\nconst debug = Debug('botkit:webex');\n\nexport interface WebexAdapterOptions {\n    /**\n     * An access token for the bot. Get one from [https://developer.webex.com/](https://developer.webex.com/)\n     */\n    access_token: string;\n    /**\n     * Secret used to validate incoming webhooks - you can define this yourself\n     */\n    secret?: string;\n    /**\n     * The root URL of your bot application.  Something like `https://mybot.com/`\n     */\n    public_address: string;\n    /**\n     * a name for the webhook subscription that will be created to tell Webex to send your bot webhooks.\n     */\n    webhook_name?: string;\n    /**\n     * Allow the adapter to startup without a complete configuration.\n     * This is risky as it may result in a non-functioning or insecure adapter.\n     * This should only be used when getting started.\n     */\n    enable_incomplete?: boolean;\n}\n\n/**\n * Connect [Botkit](https://www.npmjs.com/package/botkit) or [BotBuilder](https://www.npmjs.com/package/botbuilder) to Webex Teams.\n */\nexport class WebexAdapter extends BotAdapter {\n    private options: WebexAdapterOptions;\n\n    private _api: Webex;\n    private _identity: any;\n\n    /**\n     * Name used by Botkit plugin loader\n     * @ignore\n     */\n    public name = 'Webex Adapter';\n\n    /**\n     * Object containing one or more Botkit middlewares to bind automatically.\n     * @ignore\n     */\n    public middlewares;\n\n    /**\n     * A customized BotWorker object that exposes additional utility methods.\n     * @ignore\n     */\n    public botkit_worker = WebexBotWorker;\n\n    /**\n     * Create a Webex adapter. See [WebexAdapterOptions](#webexadapteroptions) for a full definition of the allowed parameters.\n     *\n     * Use with Botkit:\n     *```javascript\n     * const adapter = new WebexAdapter({\n     *      access_token: process.env.ACCESS_TOKEN, // access token from https://developer.webex.com\n     *      public_address: process.env.PUBLIC_ADDRESS,  // public url of this app https://myapp.com/\n     *      secret: process.env.SECRET // webhook validation secret - you can define this yourself\n     * });\n     * const controller = new Botkit({\n     *      adapter: adapter,\n     *      // ... other configuration options\n     * });\n     * ```\n     *\n     * Use with BotBuilder:\n     *```javascript\n     * const adapter = new WebexAdapter({\n     *      access_token: process.env.ACCESS_TOKEN, // access token from https://developer.webex.com\n     *      public_address: process.env.PUBLIC_ADDRESS,  // public url of this app https://myapp.com/\n     *      secret: process.env.SECRET // webhook validation secret - you can define this yourself\n     * });\n     *\n     * // set up restify...\n     * const server = restify.createServer();\n     * server.use(restify.plugins.bodyParser());\n     * // register the webhook subscription to start receiving messages - Botkit does this automatically!\n     * adapter.registerWebhookSubscription('/api/messages');\n     * // Load up the bot's identity, otherwise it won't know how to filter messages from itself\n     * adapter.getIdentity();\n     * // create an endpoint for receiving messages\n     * server.post('/api/messages', (req, res) => {\n     *      adapter.processActivity(req, res, async(context) => {\n     *          // do your bot logic here!\n     *      });\n     * });\n     * ```\n     *\n     * @param options An object containing API credentials, a webhook verification token and other options\n     */\n    public constructor(config: WebexAdapterOptions) {\n        super();\n\n        this.options = {\n            ...config\n        };\n\n        if (!this.options.access_token) {\n            const err = 'Missing required parameter `access_token`';\n            if (!this.options.enable_incomplete) {\n                throw new Error(err);\n            } else {\n                console.error(err);\n            }\n        } else {\n            this._api = Webex.init({\n                credentials: {\n                    authorization: {\n                        access_token: this.options.access_token\n                    }\n                }\n            });\n\n            if (!this._api) {\n                const err = 'Could not create the Webex Teams API client';\n                if (!this.options.enable_incomplete) {\n                    throw new Error(err);\n                } else {\n                    console.error(err);\n                }\n            }\n        }\n\n        if (!this.options.public_address) {\n            const err = 'Missing required parameter `public_address`';\n            if (!this.options.enable_incomplete) {\n                throw new Error(err);\n            } else {\n                console.error(err);\n            }\n        } else {\n            const endpoint = new url.URL(this.options.public_address);\n            if (!endpoint.hostname) {\n                throw new Error('Could not determine hostname of public address: ' + this.options.public_address);\n            } else {\n                this.options.public_address = endpoint.hostname + (endpoint.port ? ':' + endpoint.port : '');\n            }\n        }\n\n        if (!this.options.secret) {\n            console.warn('WARNING: No secret specified. Source of incoming webhooks will not be validated. https://developer.webex.com/webhooks-explained.html#auth');\n        }\n\n        if (this.options.enable_incomplete) {\n            const warning = [\n                '',\n                '****************************************************************************************',\n                '* WARNING: Your adapter may be running with an incomplete/unsafe configuration.        *',\n                '* - Ensure all required configuration options are present                              *',\n                '* - Disable the \"enable_incomplete\" option!                                            *',\n                '****************************************************************************************',\n                ''\n            ];\n            console.warn(warning.join('\\n'));\n        }\n\n        // Botkit Plugin additions\n        this.middlewares = {\n            spawn: [\n                async (bot, next): Promise<void> => {\n                    // make webex api directly available on a botkit instance.\n                    bot.api = this._api;\n\n                    next();\n                }\n            ]\n        };\n    }\n\n    /**\n     * Load the bot's identity via the Webex API.\n     * MUST be called by BotBuilder bots in order to filter messages sent by the bot.\n     */\n    public async getIdentity(): Promise<any> {\n        return new Promise((resolve, reject) => {\n            if (this._api) {\n                this._api.people.get('me').then((identity) => {\n                    debug('Webex: My identity is', identity);\n                    this._identity = identity;\n                    resolve(identity);\n                }).catch((err) => {\n                    reject(err);\n                });\n            } else {\n                reject(new Error('No API client configured'));\n            }\n        });\n    }\n\n    /**\n     * Returns the identity of the bot, including {id, emails, displayName, created} and anything else from [this spec](https://webex.github.io/spark-js-sdk/api/#personobject)\n     */\n    public get identity(): any {\n        return this._identity || {};\n    }\n\n    /**\n     * Botkit-only: Initialization function called automatically when used with Botkit.\n     *      * Calls registerWebhookSubscription() during bootup.\n     *      * Calls getIdentit() to load the bot's identity.\n     */\n    public init(botkit): void {\n        // when the bot is ready, register the webhook subscription with the Webex API\n\n        botkit.addDep('webex-identity');\n\n        this.getIdentity().then(() => {\n            botkit.completeDep('webex-identity');\n        }).catch((err) => {\n            throw new Error(err);\n        });\n\n        botkit.ready(() => {\n            debug('Registering webhook subscription!');\n            botkit.adapter.registerWebhookSubscription(botkit.getConfig('webhook_uri'));\n        });\n    }\n\n    /**\n     * Clear out and reset all the webhook subscriptions currently associated with this application.\n     */\n    public async resetWebhookSubscriptions(): Promise<any> {\n        return new Promise<void>((resolve, reject) => {\n            this._api.webhooks.list().then(async (list) => {\n                for (let i = 0; i < list.items.length; i++) {\n                    await this._api.webhooks.remove(list.items[i]).catch(reject);\n                }\n                resolve();\n            });\n        });\n    };\n\n    /**\n     * Register a webhook subscription with Webex Teams to start receiving message events.\n     * @param webhook_path the path of the webhook endpoint like `/api/messages`\n     */\n    public registerWebhookSubscription(webhook_path): void {\n        const webhook_name = this.options.webhook_name || 'Botkit Firehose';\n\n        this._api.webhooks.list().then((list) => {\n            let hook_id = null;\n\n            for (let i = 0; i < list.items.length; i++) {\n                if (list.items[i].name === webhook_name) {\n                    hook_id = list.items[i].id;\n                }\n            }\n\n            const hook_url = 'https://' + this.options.public_address + webhook_path;\n\n            debug('Webex: incoming webhook url is ', hook_url);\n\n            if (hook_id) {\n                this._api.webhooks.update({\n                    id: hook_id,\n                    resource: 'all',\n                    targetUrl: hook_url,\n                    event: 'all',\n                    secret: this.options.secret,\n                    name: webhook_name\n                }).then(function() {\n                    debug('Webex: SUCCESSFULLY UPDATED WEBEX WEBHOOKS');\n                }).catch(function(err) {\n                    console.error('FAILED TO REGISTER WEBHOOK', err);\n                    throw new Error(err);\n                });\n            } else {\n                this._api.webhooks.create({\n                    resource: 'all',\n                    targetUrl: hook_url,\n                    event: 'all',\n                    secret: this.options.secret,\n                    name: webhook_name\n                }).then(function() {\n                    debug('Webex: SUCCESSFULLY REGISTERED WEBEX WEBHOOKS');\n                }).catch(function(err) {\n                    console.error('FAILED TO REGISTER WEBHOOK', err);\n                    throw new Error(err);\n                });\n            }\n        }).catch(function(err) {\n            throw new Error(err);\n        });\n    }\n\n    /**\n     * Register a webhook subscription with Webex Teams to start receiving message events.\n     * @param webhook_path the path of the webhook endpoint like `/api/messages`\n     */\n    public registerAdaptiveCardWebhookSubscription(webhook_path): void {\n        const webhook_name = this.options.webhook_name || 'Botkit AttachmentActions';\n\n        this._api.webhooks.list().then((list) => {\n            let hook_id = null;\n\n            for (let i = 0; i < list.items.length; i++) {\n                if (list.items[i].name === webhook_name) {\n                    hook_id = list.items[i].id;\n                }\n            }\n\n            const hook_url = 'https://' + this.options.public_address + webhook_path;\n\n            debug('Webex: incoming webhook url is ', hook_url);\n\n            if (hook_id) {\n                this._api.webhooks.update({\n                    id: hook_id,\n                    resource: 'attachmentActions',\n                    targetUrl: hook_url,\n                    event: 'all',\n                    secret: this.options.secret,\n                    name: webhook_name\n                }).then(function() {\n                    debug('Webex: SUCCESSFULLY UPDATED WEBEX WEBHOOKS');\n                }).catch(function(err) {\n                    console.error('FAILED TO REGISTER WEBHOOK', err);\n                    throw new Error(err);\n                });\n            } else {\n                this._api.webhooks.create({\n                    resource: 'attachmentActions',\n                    targetUrl: hook_url,\n                    event: 'all',\n                    secret: this.options.secret,\n                    name: webhook_name\n                }).then(function() {\n                    debug('Webex: SUCCESSFULLY REGISTERED WEBEX WEBHOOKS');\n                }).catch(function(err) {\n                    console.error('FAILED TO REGISTER WEBHOOK', err);\n                    throw new Error(err);\n                });\n            }\n        }).catch(function(err) {\n            throw new Error(err);\n        });\n    }\n\n    /**\n     * Standard BotBuilder adapter method to send a message from the bot to the messaging API.\n     * [BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#sendactivities).\n     * @param context A TurnContext representing the current incoming message and environment.\n     * @param activities An array of outgoing activities to be sent back to the messaging API.\n     */\n    public async sendActivities(context: TurnContext, activities: Partial<Activity>[]): Promise<ResourceResponse[]> {\n        const responses = [];\n        for (let a = 0; a < activities.length; a++) {\n            const activity = activities[a];\n            if (activity.type === ActivityTypes.Message) {\n                debug('OUTGOING ACTIVITY', activity);\n\n                // transform activity into the webex message format\n                // https://developer.webex.com/docs/api/v1/messages/create-a-message\n                const message: any = {};\n                if (activity.channelData && activity.channelData.files) {\n                    message.files = activity.channelData.files;\n                }\n                if (activity.text) {\n                    message.text = activity.text;\n                }\n                if (activity.channelData && activity.channelData.markdown) {\n                    message.markdown = activity.channelData.markdown;\n                }\n                if (activity.conversation && activity.conversation.id) {\n                    message.roomId = activity.conversation.id;\n                } else if (!activity.conversation && activity.recipient.id) {\n                    message.toPersonId = activity.recipient.id;\n                } else if (activity.channelData && activity.channelData.toPersonEmail) {\n                    message.toPersonEmail = activity.channelData.toPersonEmail;\n                }\n\n                if (activity.attachments) {\n                    message.attachments = activity.attachments;\n                } else if (activity.channelData && activity.channelData.attachments) {\n                    message.attachments = activity.channelData.attachments;\n                }\n\n                // @ts-ignore ignore this webex specific field\n                if (activity.conversation && activity.conversation.parentId) {\n                    // @ts-ignore ignore this webex specific field\n                    message.parentId = activity.conversation.parentId;\n                } else if (activity.channelData && activity.channelData.parentId) {\n                    message.parentId = activity.channelData.parentId;\n                }\n\n                const response = await this._api.messages.create(message);\n\n                responses.push(response);\n            } else {\n                // If there are ever any non-message type events that need to be sent, do it here.\n                debug('Unknown message type encountered in sendActivities: ', activity.type);\n            }\n        }\n\n        return responses;\n    }\n\n    /**\n     * Webex adapter does not support updateActivity.\n     * @ignore\n     */\n    // eslint-disable-next-line\n    public async updateActivity(context: TurnContext, activity: Partial<Activity>): Promise<void> {\n        debug('Webex adapter does not support updateActivity.');\n    }\n\n    /**\n     * Standard BotBuilder adapter method to delete a previous message.\n     * [BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#deleteactivity).\n     * @param context A TurnContext representing the current incoming message and environment. (not used)\n     * @param reference An object in the form `{activityId: <id of message to delete>, conversation: { id: <id of slack channel>}}`\n     */\n    public async deleteActivity(context: TurnContext, reference: Partial<ConversationReference>): Promise<void> {\n        if (reference.activityId) {\n            try {\n                await this._api.messages.remove({ id: reference.activityId });\n            } catch (err) {\n                throw new Error(err);\n            }\n        } else {\n            throw new Error('Cannot delete activity: reference is missing activityId');\n        }\n    }\n\n    /**\n     * Standard BotBuilder adapter method for continuing an existing conversation based on a conversation reference.\n     * [BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#continueconversation)\n     * @param reference A conversation reference to be applied to future messages.\n     * @param logic A bot logic function that will perform continuing action in the form `async(context) => { ... }`\n     */\n    public async continueConversation(reference: Partial<ConversationReference>, logic: (context: TurnContext) => Promise<void>): Promise<void> {\n        const request = TurnContext.applyConversationReference(\n            { type: 'event', name: 'continueConversation' },\n            reference,\n            true\n        );\n        const context = new TurnContext(this, request);\n\n        return this.runMiddleware(context, logic);\n    }\n\n    /**\n     * Accept an incoming webhook request and convert it into a TurnContext which can be processed by the bot's logic.\n     * @param req A request object from Restify or Express\n     * @param res A response object from Restify or Express\n     * @param logic A bot logic function in the form `async(context) => { ... }`\n     */\n    public async processActivity(req, res, logic: (context: TurnContext) => Promise<void>): Promise<any> {\n        res.status(200);\n        res.end();\n\n        const payload = req.body;\n        let activity;\n\n        if (this.options.secret) {\n            const signature = req.headers['x-spark-signature'];\n            const hash = crypto.createHmac('sha1', this.options.secret).update(JSON.stringify(payload)).digest('hex');\n            if (signature !== hash) {\n                console.warn('WARNING: Webhook received message with invalid signature. Potential malicious behavior!');\n                return false;\n            }\n        }\n\n        if (payload.resource === 'messages' && payload.event === 'created') {\n            const decrypted_message = await this._api.messages.get(payload.data);\n\n            activity = {\n                id: decrypted_message.id,\n                timestamp: new Date(),\n                channelId: 'webex',\n                conversation: { id: decrypted_message.roomId, parentId: decrypted_message.parentId },\n                from: { id: decrypted_message.personId, name: decrypted_message.personEmail },\n                recipient: { id: this.identity.id },\n                text: decrypted_message.text,\n                channelData: decrypted_message,\n                type: ActivityTypes.Message,\n                parentId: decrypted_message.parentId\n            };\n\n            // add in some fields from the original payload\n            activity.channelData.orgId = payload.orgId;\n            activity.channelData.createdBy = payload.createdBy;\n            activity.channelData.appId = payload.appId;\n            activity.channelData.actorId = payload.actorId;\n\n            // this is the bot speaking\n            if (activity.from.id === this.identity.id) {\n                activity.channelData.botkitEventType = 'self_message';\n                activity.type = ActivityTypes.Event;\n            } else {\n                // change the event type of messages sent in 1:1s\n                if (activity.channelData.roomType === 'direct') {\n                    activity.channelData.botkitEventType = 'direct_message';\n                }\n            }\n\n            if (decrypted_message.html) {\n                // strip the mention & HTML from the message\n                let pattern = new RegExp('^(<p>|<div>)?<spark-mention .*?data-object-id=\"' + this.identity.id + '\".*?>.*?</spark-mention>', 'im');\n                if (!decrypted_message.html.match(pattern)) {\n                    const encoded_id = this.identity.id;\n                    const decoded = Buffer.from(encoded_id, 'base64').toString('ascii');\n\n                    // this should look like ciscospark://us/PEOPLE/<id string>\n                    let matches;\n                    if ((matches = decoded.match(/ciscospark:\\/\\/.*\\/(.*)/im))) {\n                        pattern = new RegExp('^(<p>|<div>)?<spark-mention .*?data-object-id=\"' + matches[1] + '\".*?>.*?</spark-mention>', 'im');\n                    }\n                }\n                let action = decrypted_message.html.replace(pattern, '');\n\n                // strip the remaining HTML tags\n                action = action.replace(/<.*?>/img, '');\n\n                // strip remaining whitespace\n                action = action.trim();\n\n                // replace the message text with the the HTML version\n                activity.text = action;\n            } else {\n                const pattern = new RegExp('^' + this.identity.displayName + '\\\\s+', 'i');\n                if (activity.text) {\n                    activity.text = activity.text.replace(pattern, '');\n                }\n            }\n\n            // create a conversation reference\n            const context = new TurnContext(this, activity);\n\n            this.runMiddleware(context, logic)\n                .catch((err) => { console.error(err.toString()); });\n        } else if (payload.resource === 'attachmentActions' && payload.event === 'created') {\n            const decrypted_message = await this._api.attachmentActions.get(payload.data);\n\n            activity = {\n                id: decrypted_message.id,\n                timestamp: new Date(),\n                channelId: 'webex',\n                conversation: { id: decrypted_message.roomId },\n                from: { id: decrypted_message.personId, name: decrypted_message.personEmail },\n                recipient: { id: this.identity.id },\n                value: decrypted_message.inputs,\n                channelData: decrypted_message,\n                type: ActivityTypes.Event\n            };\n\n            // add in some fields from the original payload\n            activity.channelData.orgId = payload.orgId;\n            activity.channelData.createdBy = payload.createdBy;\n            activity.channelData.appId = payload.appId;\n            activity.channelData.actorId = payload.actorId;\n\n            activity.channelData.botkitEventType = 'attachmentActions';\n\n            // create a conversation reference\n            const context = new TurnContext(this, activity);\n\n            this.runMiddleware(context, logic)\n                .catch((err) => { console.error(err.toString()); });\n        } else {\n            // type == payload.resource + '.' + payload.event\n            // memberships.deleted for example\n            // payload.data contains stuff\n            activity = {\n                id: payload.id,\n                timestamp: new Date(),\n                channelId: 'webex',\n                conversation: { id: payload.data.roomId },\n                from: { id: payload.actorId },\n                recipient: { id: this.identity.id },\n                channelData: {\n                    ...payload,\n                    botkitEventType: payload.resource + '.' + payload.event\n                },\n                type: ActivityTypes.Event\n            };\n\n            const context = new TurnContext(this, activity);\n\n            this.runMiddleware(context, logic)\n                .catch((err) => { console.error(err.toString()); });\n        }\n    }\n}\n"
  },
  {
    "path": "packages/botbuilder-adapter-webex/tests/WebexAdapter.tests.js",
    "content": "const assert = require('assert');\nconst { WebexAdapter } = require('../');\n\ndescribe('WebexAdapter', function() {\n\n    let adapter;\n\n    beforeEach(function () {\n        adapter = new WebexAdapter({\n            access_token: '123123123',\n            secret: '123',\n            public_address: 'https://fakebot.com'\n        });\n    });\n\n    it('should not construct without required parameters', function () {\n        assert.throws(function () { let adapter = new WebexAdapter({}) }, 'Foo');\n    });\n\n    it('should create a WebexAdapter object', function () {\n        assert((adapter instanceof WebexAdapter), 'Adapter is wrong type');\n    });\n\n});\n"
  },
  {
    "path": "packages/botbuilder-adapter-webex/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2015\",\n    \"module\": \"commonjs\",\n    \"declaration\": true,\n    \"sourceMap\": true,\n    \"outDir\": \"./lib\",\n    \"rootDir\": \"./src\",\n    \"types\" : [\"node\"],\n    \"lib\": [\n      \"es5\",\n      \"es2015\",\n      \"es2016.array.include\",\n      \"esnext.asynciterable\",\n      \"dom\"\n    ]\n  },\n  \"include\": [\n    \"src/**/*\"\n  ]\n}"
  },
  {
    "path": "packages/botkit/.eslintrc.js",
    "content": "module.exports = {\n    \"extends\": \"standard\",\n    \"rules\": {\n        \"semi\": [2, \"always\"],\n        \"indent\": [2, 4],\n        \"no-return-await\": 0,\n        \"camelcase\": 0,\n        \"no-unused-vars\": 0,\n        \"@typescript-eslint/no-object-literal-type-assertion\": 0,\n        \"@typescript-eslint/indent\": 0,\n        \"@typescript-eslint/explicit-member-accessibility\": 1,\n        \"space-before-function-paren\": [2, {\n            \"named\": \"never\",\n            \"anonymous\": \"never\",\n            \"asyncArrow\": \"always\"\n        }],\n        \"template-curly-spacing\": [2, \"always\"]\n    }\n};"
  },
  {
    "path": "packages/botkit/.gitignore",
    "content": "node_modules/\nlib/\n.nyc_output"
  },
  {
    "path": "packages/botkit/LICENSE.md",
    "content": "Copyright XOXCO, Inc, http://xoxco.com, http://howdy.ai\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "packages/botkit/README.md",
    "content": "# Botkit - Building Blocks for Building Bots\n\n[![npm](https://img.shields.io/npm/v/botkit.svg)](https://www.npmjs.com/package/botkit)\n[![David](https://img.shields.io/david/howdyai/botkit.svg)](https://david-dm.org/howdyai/botkit)\n[![npm](https://img.shields.io/npm/l/botkit.svg)](https://spdx.org/licenses/MIT)\n[![Build Status](https://travis-ci.com/howdyai/botkit.svg?branch=master)](https://travis-ci.com/howdyai/botkit)\n\n**Botkit is an open source developer tool for building chat bots, apps and custom integrations for major messaging platforms.**\n\n## The information in this document is for the brand new 4.0 branch of Botkit! If you're looking for documentation for previous versions, [look here](https://github.com/howdyai/botkit-docs).\n\n## Install Botkit\n\nThe best way to get started locally with Botkit is by installing our Yeoman template, and using it to create a new Botkit project. \nThis will install and configure a starter kit for you!\n\n```bash\nnpm install -g yo generator-botkit\nyo botkit\n```\n\n### Remix on Glitch\n\nWant to dive right in? [Remix one of our starter kits on Glitch](https://glitch.com/botkit). You'll start with a fully functioning app that you can edit and run from the browser!\n\n [![Remix on Glitch](https://github.com/howdyai/botkit/blob/main/packages/docs/glitch.png?raw=true)](https://glitch.com/botkit)\n\n## Build Your Bot\n\nThe goal of Botkit is to make it easier and more fun to build software that talks and works like a robot! \nBuilding a bot should feel cool, and not too technically complicated.\n\nBotkit handles all the nitty gritty details like\nAPI calls, session management and authentication,\nallowing you to focus on building COOL FEATURES for your\nbot using middleware and event handlers.\n\nThe toolkit is designed to provide meaningful building blocks for creating conversational user interfaces - with functions like `hears()`, `ask()`, and `reply()` that do what they say they do.\n\nThe [full documentation for Botkit's capabilities begins here &raquo;](../docs/index.md)\n\n## Platform Support\n\nBotkit can connect to multiple messaging channels through the [Microsoft Bot Framework Service](https://dev.botframework.com).\nNo plugins are necessary to use the Bot Framework service, and bots can be developed locally using the [Bot Framework Emulator](https://aka.ms/botframework-emulator).\n\nThe Botkit project includes several official adapters. Using these plugins, your bot can communicate directly with the messaging platforms.\n\n* [Self-hosted web chat](../botbuilder-adapter-web)\n* [Slack](../botbuilder-adapter-slack)\n* [Webex Teams](../botbuilder-adapter-webex)\n* [Facebook Messenger](../botbuilder-adapter-facebook)\n* [Twilio SMS](../botbuilder-adapter-twilio-sms)\n* [Google Hangouts](../botbuilder-adapter-hangouts)\n\nAdditional adapters can be found by [searching npm for Bot Framework-compatible adapters](https://www.npmjs.com/search?q=botbuilder-adapter). The open source community has created a variety of plugins and extensions to Bot Framework.  Check out the [Bot Builder Community Repo](https://github.com/BotBuilderCommunity/botbuilder-community-js) for additional adapters, storage connectors and middlewares.\n\n[Platform specific documentation can be found on the main docs site  &raquo;](../docs/platforms/index.md)\n\n### Hearing Keywords\n\nMost bots do their thing by listening for keywords, phrases or patterns in messages from users. Botkit has a special event handler called `hears()` that makes it easy to configure your bot to listen for this type of trigger.\n\n```javascript\ncontroller.hears(['string','pattern .*',new RegExp('.*','i')],'message,other_event', async (bot, message) => {\n\n  // do something!\n  await bot.reply(message, 'I heard a message.')\n\n});\n```\n\n[Read more about hearing things &rsaquo;](../docs/core.md#matching-patterns-and-keywords-with-hears)\n\n### Responding to Events\n\nBots can respond to non-verbal events as well, like when a new user joins a channel, a file gets uploaded, or a button gets clicked. These events are handled using an event handling pattern that should look familiar. Most events in Botkit can be replied to like normal messages.\n\n```javascript\ncontroller.on('channel_join', async (bot, message) => {\n\n  await bot.reply(message,'Welcome to the channel!');\n\n});\n```\n\n[See a full list of events and more information about handling them &rsaquo;](../docs/core.md#receiving-messages-and-events)\n\n### Middleware\n\nIn addition to taking direct action in response to a certain message or type of event, Botkit can also take passive action on messages as they move through the application using middlewares. Middleware functions work by changing messages, adding new fields, firing alternate events, and modifying or overriding the behavior of Botkit's core features.\n\nMiddleware can be used to adjust how Botkit receives, processes, and sends messages.\n\n```javascript\n// Log every message received\ncontroller.middleware.receive.use(function(bot, message, next) {\n\n  // log it\n  console.log('RECEIVED: ', message);\n\n  // modify the message\n  message.logged = true;\n\n  // continue processing the message\n  next();\n\n});\n\n// Log every message sent\ncontroller.middleware.send.use(function(bot, message, next) {\n\n  // log it\n  console.log('SENT: ', message);\n\n  // modify the message\n  message.logged = true;\n\n  // continue processing the message\n  next();\n\n});\n```\n## Documentation\n\n[Full documentation of Botkit, including a class reference, can be found on the docs site](../docs/index.md).\n\n## [Change Log](https://github.com/howdyai/botkit/blob/master/changelog.md)\n\n## Community & Support\n\nJoin our thriving community of Botkit developers and bot enthusiasts at large.\nOver 10,000 members strong, [our Github site](https://github.com/howdyai/botkit) is\n_the place_ for people interested in the art and science of making bots.\nCome to ask questions, share your progress, and commune with your peers!\n\nYou can also find help from members of the Botkit team [in our dedicated Cisco Spark room](https://eurl.io/#SyNZuomKx)!\n\n## About Botkit\n\nBotkit is a part of the [Microsoft Bot Framework](https://dev.botframework.com).\n\nWant to contribute? [Read the contributor guide](https://github.com/howdyai/botkit/blob/master/CONTRIBUTING.md)\n\nBotkit is released under the [MIT Open Source license](https://github.com/howdyai/botkit/blob/master/LICENSE.md)\n"
  },
  {
    "path": "packages/botkit/package.json",
    "content": "{\n  \"name\": \"botkit\",\n  \"version\": \"4.15.0\",\n  \"description\": \"Building Blocks for Building Bots\",\n  \"main\": \"lib/index.js\",\n  \"typings\": \"./lib/index.d.ts\",\n  \"files\": [\n    \"/lib\",\n    \"/src\"\n  ],\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"eslint\": \"./node_modules/.bin/eslint --fix src/*\",\n    \"test\": \"tsc ; nyc mocha tests/*.tests.js\",\n    \"pack\": \"npm pack\"\n  },\n  \"author\": \"benbrown@gmail.com\",\n  \"license\": \"MIT\",\n  \"keywords\": [\n    \"botkit\",\n    \"botbuilder\",\n    \"botframework\",\n    \"bots\",\n    \"chatbots\"\n  ],\n  \"homepage\": \"https://github.com/howdyai/botkit/blob/master/packages/botkit#readme\",\n  \"bugs\": {\n    \"url\": \"https://github.com/howdyai/botkit/issues\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/howdyai/botkit.git\"\n  },\n  \"dependencies\": {\n    \"body-parser\": \"^1.19.0\",\n    \"botbuilder\": \"^4.15.0\",\n    \"botbuilder-core\": \"^4.15.0\",\n    \"botbuilder-dialogs\": \"^4.15.0\",\n    \"botframework-connector\": \"^4.15.0\",\n    \"debug\": \"^4.1.0\",\n    \"express\": \"^4.17.1\",\n    \"mustache\": \"^4.0.1\",\n    \"path\": \"^0.12.7\",\n    \"ware\": \"^1.3.0\"\n  },\n  \"devDependencies\": {\n    \"@types/debug\": \"^4.1.5\",\n    \"@types/express\": \"^4.17.2\",\n    \"@types/node\": \"^10.17.5\",\n    \"eslint\": \"^8.3.0\",\n    \"eslint-config-standard\": \"^16.0.3\",\n    \"eslint-plugin-import\": \"^2.25.3\",\n    \"eslint-plugin-node\": \"^11.1.0\",\n    \"eslint-plugin-promise\": \"^5.1.1\",\n    \"eslint-plugin-standard\": \"^4.0.1\"\n}\n}\n"
  },
  {
    "path": "packages/botkit/src/adapter.ts",
    "content": "/**\n * @module botkit\n */\n/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\nimport { BotFrameworkAdapter, TurnContext, TeamsInfo, ChannelInfo } from 'botbuilder';\nimport { ConnectorClient, TokenApiClient } from 'botframework-connector';\nimport { TeamsBotWorker } from './teamsHelpers';\nimport * as os from 'os';\n\nconst pjson: any = require('../package.json'); // eslint-disable-line @typescript-eslint/no-var-requires\n\n// Retrieve additional information, i.e., host operating system, host OS release, architecture, Node.js version\nconst ARCHITECTURE: any = os.arch();\nconst TYPE: any = os.type();\nconst RELEASE: any = os.release();\nconst NODE_VERSION: any = process.version;\nconst USER_AGENT: string = `Microsoft-BotFramework/3.1 Botkit/${ pjson.version } ` +\n    `(Node.js,Version=${ NODE_VERSION }; ${ TYPE } ${ RELEASE }; ${ ARCHITECTURE })`;\n\n/**\n * This class extends the [BotFrameworkAdapter](https://docs.microsoft.com/en-us/javascript/api/botbuilder/botframeworkadapter?view=botbuilder-ts-latest) with a few additional features to support Microsoft Teams.\n * * Changes userAgent to reflect Botkit instead of BotBuilder\n * * Adds getChannels() (MS Teams)\n * * Adds middleware for adjusting location of tenant id field (MS Teams)\n */\nexport class BotkitBotFrameworkAdapter extends BotFrameworkAdapter {\n    public botkit_worker = TeamsBotWorker;\n\n    /**\n     * Allows for mocking of the connector client in unit tests.\n     * Overridden by Botkit in order to change userAgent.\n     * @ignore\n     * @param serviceUrl Clients service url.\n     */\n    public createConnectorClient(serviceUrl: string): ConnectorClient {\n        const client: ConnectorClient = new ConnectorClient(this.credentials, { baseUri: serviceUrl, userAgent: USER_AGENT });\n        return client;\n    }\n\n    /**\n     * Allows for mocking of the OAuth API Client in unit tests.\n     * Overridden by Botkit in order to change userAgent.\n     * @ignore\n     * @param serviceUrl Clients service url.\n     */\n    protected createTokenApiClient(serviceUrl: string): TokenApiClient {\n        const client = new TokenApiClient(this.credentials, { baseUri: serviceUrl, userAgent: USER_AGENT });\n        return client;\n    }\n\n    /**\n     * Get the list of channels in a MS Teams team.\n     * Can only be called with a TurnContext that originated in a team conversation - 1:1 conversations happen _outside a team_ and thus do not contain the required information to call this API.\n     * @param context A TurnContext object representing a message or event from a user in Teams\n     * @returns an array of channels in the format [{name: string, id: string}]\n     */\n    public async getChannels(context: TurnContext): Promise<ChannelInfo[]> {\n        if (context.activity.channelData && context.activity.channelData.team) {\n            const channels = await TeamsInfo.getTeamChannels(context);\n            return channels ? channels.map((c) => { if (!c.name) { c.name = 'General'; } return c; }) : [];\n        } else {\n            console.error('getChannels cannot be called from unknown team');\n            return [];\n        }\n    }\n}\n"
  },
  {
    "path": "packages/botkit/src/botworker.ts",
    "content": "/**\n * @module botkit\n */\n/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\nimport { Botkit, BotkitMessage } from './core';\nimport { Activity, ConversationAccount, ConversationReference, ConversationParameters, TurnContext } from 'botbuilder';\nimport { DialogTurnResult, Dialog } from 'botbuilder-dialogs';\n\n/**\n * A base class for a `bot` instance, an object that contains the information and functionality for taking action in response to an incoming message.\n * Note that adapters are likely to extend this class with additional platform-specific methods - refer to the adapter documentation for these extensions.\n */\nexport class BotWorker {\n    private _controller: Botkit;\n    private _config: any;\n\n    /**\n     * Create a new BotWorker instance. Do not call this directly - instead, use [controller.spawn()](#spawn).\n     * @param controller A pointer to the main Botkit controller\n     * @param config An object typically containing { dialogContext, reference, context, activity }\n     */\n    public constructor(controller: Botkit, config) {\n        this._controller = controller;\n        this._config = {\n            ...config\n        };\n    }\n\n    /**\n     * Get a reference to the main Botkit controller.\n     */\n    public get controller(): Botkit {\n        return this._controller;\n    }\n\n    /**\n     * Get a value from the BotWorker's configuration.\n     *\n     * ```javascript\n     * let original_context = bot.getConfig('context');\n     * await original_context.sendActivity('send directly using the adapter instead of Botkit');\n     * ```\n     *\n     * @param {string} key The name of a value stored in the configuration\n     * @returns {any} The value stored in the configuration (or null if absent)\n     */\n    public getConfig(key?: string): any {\n        if (key) {\n            return this._config[key];\n        } else {\n            return this._config;\n        }\n    }\n\n    /**\n     * Send a message using whatever context the `bot` was spawned in or set using [changeContext()](#changecontext) --\n     * or more likely, one of the platform-specific helpers like\n     * [startPrivateConversation()](../reference/slack.md#startprivateconversation) (Slack),\n     * [startConversationWithUser()](../reference/twilio-sms.md#startconversationwithuser) (Twilio SMS),\n     * and [startConversationWithUser()](../reference/facebook.md#startconversationwithuser) (Facebook Messenger).\n     * Be sure to check the platform documentation for others - most adapters include at least one.\n     *\n     * Simple use in event handler (acts the same as bot.reply)\n     * ```javascript\n     * controller.on('event', async(bot, message) => {\n     *\n     *  await bot.say('I received an event!');\n     *\n     * });\n     * ```\n     *\n     * Use with a freshly spawned bot and bot.changeContext:\n     * ```javascript\n     * let bot = controller.spawn(OPTIONS);\n     * bot.changeContext(REFERENCE);\n     * bot.say('ALERT! I have some news.');\n     * ```\n     *\n     * Use with multi-field message object:\n     * ```javascript\n     * controller.on('event', async(bot, message) => {\n     *      bot.say({\n     *          text: 'I heard an event',\n     *          attachments: [\n     *              title: message.type,\n     *              text: `The message was of type ${ message.type }`,\n     *              // ...\n     *          ]\n     *      });\n     * });\n     * ```\n     *\n     * @param message A string containing the text of a reply, or more fully formed message object\n     * @returns Return value will contain the results of the send action, typically `{id: <id of message>}`\n     */\n    public async say(message: Partial<BotkitMessage> | string): Promise<any> {\n        return new Promise((resolve, reject) => {\n            const activity = this.ensureMessageFormat(message);\n\n            this._controller.middleware.send.run(this, activity, async (err, bot, activity) => {\n                if (err) {\n                    return reject(err);\n                }\n                resolve(await this.getConfig('context').sendActivity(activity));\n            });\n        });\n    };\n\n    /**\n     * Reply to an incoming message.\n     * Message will be sent using the context of the source message, which may in some cases be different than the context used to spawn the bot.\n     *\n     * Note that like [bot.say()](#say), `reply()` can take a string or a message object.\n     *\n     * ```javascript\n     * controller.on('event', async(bot, message) => {\n    *\n    *  await bot.reply(message, 'I received an event and am replying to it.');\n    *\n    * });\n    * ```\n    *\n    * @param src An incoming message, usually passed in to a handler function\n    * @param resp A string containing the text of a reply, or more fully formed message object\n    * @returns Return value will contain the results of the send action, typically `{id: <id of message>}`\n    */\n    public async reply(src: Partial<BotkitMessage>, resp: Partial<BotkitMessage> | string): Promise<any> {\n        let activity = this.ensureMessageFormat(resp);\n\n        // Get conversation reference from src\n        const reference = TurnContext.getConversationReference(src.incoming_message);\n\n        activity = TurnContext.applyConversationReference(activity, reference);\n\n        return this.say(activity);\n    }\n\n    /**\n     * Begin a pre-defined dialog by specifying its id. The dialog will be started in the same context (same user, same channel) in which the original incoming message was received.\n     * [See \"Using Dialogs\" in the core documentation.](../index.md#using-dialogs)\n     *\n     * ```javascript\n     * controller.hears('hello', 'message', async(bot, message) => {\n     *      await bot.beginDialog(GREETINGS_DIALOG);\n     * });\n     * ```\n     * @param id id of dialog\n     * @param options object containing options to be passed into the dialog\n     */\n    public async beginDialog(id: string, options?: any): Promise<void> {\n        if (this._config.dialogContext) {\n            await this._config.dialogContext.beginDialog(id + ':botkit-wrapper', {\n                user: this.getConfig('context').activity.from.id,\n                channel: this.getConfig('context').activity.conversation.id,\n                ...options\n            });\n\n            // make sure we save the state change caused by the dialog.\n            // this may also get saved again at end of turn\n            await this._controller.saveState(this);\n        } else {\n            throw new Error('Call to beginDialog on a bot that did not receive a dialogContext during spawn');\n        }\n    }\n\n    /**\n     * Cancel any and all active dialogs for the current user/context.\n     */\n    public async cancelAllDialogs(): Promise<DialogTurnResult> {\n        if (this._config.dialogContext) {\n            return this._config.dialogContext.cancelAllDialogs();\n        }\n    }\n\n    /**\n     * Get a reference to the active dialog\n     * @returns a reference to the active dialog or undefined if no dialog is active\n     */\n    public getActiveDialog(): Dialog | undefined {\n        return this.getConfig('dialogContext').activeDialog;\n    }\n\n    /**\n     * Check if any dialog is active or not\n     * @returns true if there is an active dialog, otherwise false\n     */\n    public hasActiveDialog(): boolean {\n        return !!this.getActiveDialog();\n    }\n\n    /**\n     * Check to see if a given dialog is currently active in the stack\n     * @param id The id of a dialog to look for in the dialog stack\n     * @returns true if dialog with id is located anywhere in the dialog stack\n     */\n    public isDialogActive(id: string): boolean {\n        if (this.getConfig('dialogContext').stack.length) {\n            return (this.getConfig('dialogContext').stack.filter((d) => d.id === id).length > 0);\n        }\n        return false;\n    }\n\n    /**\n     * Replace any active dialogs with a new a pre-defined dialog by specifying its id. The dialog will be started in the same context (same user, same channel) in which the original incoming message was received.\n     * [See \"Using Dialogs\" in the core documentation.](../index.md#using-dialogs)\n     *\n     * ```javascript\n     * controller.hears('hello', 'message', async(bot, message) => {\n     *      await bot.replaceDialog(GREETINGS_DIALOG);\n     * });\n     * ```\n     * @param id id of dialog\n     * @param options object containing options to be passed into the dialog\n     */\n    public async replaceDialog(id: string, options?: any): Promise<void> {\n        if (this._config.dialogContext) {\n            await this._config.dialogContext.replaceDialog(id + ':botkit-wrapper', {\n                user: this.getConfig('context').activity.from.id,\n                channel: this.getConfig('context').activity.conversation.id,\n                ...options\n            });\n\n            // make sure we save the state change caused by the dialog.\n            // this may also get saved again at end of turn\n            await this._controller.saveState(this);\n        } else {\n            throw new Error('Call to beginDialog on a bot that did not receive a dialogContext during spawn');\n        }\n    }\n\n    /**\n     * Alter the context in which a bot instance will send messages.\n     * Use this method to create or adjust a bot instance so that it can send messages to a predefined user/channel combination.\n     *\n     * ```javascript\n     * // get the reference field and store it.\n     * const saved_reference = message.reference;\n     *\n     * // later on...\n     * let bot = await controller.spawn();\n     * bot.changeContext(saved_reference);\n     * bot.say('Hello!');\n     * ```\n     *\n     * @param reference A [ConversationReference](https://docs.microsoft.com/en-us/javascript/api/botframework-schema/conversationreference?view=botbuilder-ts-latest), most likely captured from an incoming message and stored for use in proactive messaging scenarios.\n     */\n    public async changeContext(reference: Partial<ConversationReference>): Promise<BotWorker> {\n        // change context of outbound activities to use this new address\n        this._config.reference = reference;\n\n        // Create an activity using this reference\n        const activity = TurnContext.applyConversationReference(\n            { type: 'message' },\n            reference,\n            true\n        );\n\n        // create a turn context\n        const turnContext = new TurnContext(this.getConfig('adapter'), activity as Activity);\n\n        // create a new dialogContext so beginDialog works.\n        const dialogContext = await this._controller.dialogSet.createContext(turnContext);\n\n        this._config.context = turnContext;\n        this._config.dialogContext = dialogContext;\n        this._config.activity = activity;\n\n        return this;\n    }\n\n    public async startConversationWithUser(reference: any): Promise<void> {\n        // this code is mostly copied from BotFrameworkAdapter.createConversation\n\n        if (!reference.serviceUrl) { throw new Error('bot.startConversationWithUser(): missing serviceUrl.'); }\n\n        // Create conversation\n        const parameters: ConversationParameters = { bot: reference.bot, members: [reference.user], isGroup: false, activity: null, channelData: null };\n        const client = this.getConfig('adapter').createConnectorClient(reference.serviceUrl);\n\n        // Mix in the tenant ID if specified. This is required for MS Teams.\n        if (reference.conversation && reference.conversation.tenantId) {\n            // Putting tenantId in channelData is a temporary solution while we wait for the Teams API to be updated\n            parameters.channelData = { tenant: { id: reference.conversation.tenantId } };\n\n            // Permanent solution is to put tenantId in parameters.tenantId\n            parameters.tenantId = reference.conversation.tenantId;\n        }\n\n        const response = await client.conversations.createConversation(parameters);\n\n        // Initialize request and copy over new conversation ID and updated serviceUrl.\n        const request: Partial<Activity> = TurnContext.applyConversationReference(\n            { type: 'event', name: 'createConversation' },\n            reference,\n            true\n        );\n\n        const conversation: ConversationAccount = {\n            // fallback to existing conversation id because Emulator will respond without a response.id AND needs to stay in same channel.\n            // This should be fixed by Emulator. https://github.com/microsoft/BotFramework-Emulator/issues/2097\n            id: response.id || reference.conversation.id,\n            isGroup: false,\n            conversationType: null,\n            tenantId: null,\n            name: null\n        };\n        request.conversation = conversation;\n\n        if (response.serviceUrl) { request.serviceUrl = response.serviceUrl; }\n\n        // Create context and run middleware\n        const turnContext: TurnContext = this.getConfig('adapter').createContext(request);\n\n        // create a new dialogContext so beginDialog works.\n        const dialogContext = await this._controller.dialogSet.createContext(turnContext);\n\n        this._config.context = turnContext;\n        this._config.dialogContext = dialogContext;\n        this._config.activity = request;\n    }\n\n    /**\n     * Take a crudely-formed Botkit message with any sort of field (may just be a string, may be a partial message object)\n     * and map it into a beautiful BotFramework Activity.\n     * Any fields not found in the Activity definition will be moved to activity.channelData.\n     * @params message a string or partial outgoing message object\n     * @returns a properly formed Activity object\n     */\n    public ensureMessageFormat(message: Partial<BotkitMessage> | string): Partial<Activity> {\n        if (typeof (message) === 'string') {\n            return {\n                type: 'message',\n                text: message,\n                channelData: {}\n            };\n        } else {\n            // set up a base message activity\n            // https://docs.microsoft.com/en-us/javascript/api/botframework-schema/activity?view=botbuilder-ts-latest\n            const activity: Partial<Activity> = {\n                type: message.type || 'message',\n                text: message.text,\n\n                action: message.action,\n                attachmentLayout: message.attachmentLayout,\n                attachments: message.attachments,\n\n                channelData: {\n                    ...message.channelData\n                },\n                channelId: message.channelId,\n                code: message.code,\n                conversation: message.conversation,\n\n                deliveryMode: message.deliveryMode,\n                entities: message.entities,\n                expiration: message.expiration,\n                from: message.from,\n                historyDisclosed: message.historyDisclosed,\n                id: message.id,\n                importance: message.importance,\n                inputHint: message.inputHint,\n                label: message.label,\n                listenFor: message.listenFor,\n                locale: message.locale,\n                localTimestamp: message.localTimestamp,\n                localTimezone: message.localTimezone,\n                membersAdded: message.membersAdded,\n                membersRemoved: message.membersRemoved,\n                name: message.name,\n                reactionsAdded: message.reactionsAdded,\n                reactionsRemoved: message.reactionsRemoved,\n                recipient: message.recipient,\n                relatesTo: message.relatesTo,\n                replyToId: message.replyToId,\n                semanticAction: message.semanticAction,\n                serviceUrl: message.serviceUrl,\n                speak: message.speak,\n                suggestedActions: message.suggestedActions,\n                summary: message.summary,\n                textFormat: message.textFormat,\n                textHighlights: message.textHighlights,\n                timestamp: message.timestamp,\n                topicName: message.topicName,\n                value: message.value,\n                valueType: message.valueType\n            };\n\n            // Now, copy any additional fields not in the activity into channelData\n            // This way, any fields added by the developer to the root object\n            // end up in the approved channelData location.\n            for (const key in message) {\n                if (key !== 'channelData' && !Object.prototype.hasOwnProperty.call(activity, key)) {\n                    activity.channelData[key] = message[key];\n                }\n            }\n            return activity;\n        }\n    }\n\n    /**\n     * Set the http response status code for this turn\n     *\n     * ```javascript\n     * controller.on('event', async(bot, message) => {\n     *   // respond with a 500 error code for some reason!\n     *   bot.httpStatus(500);\n     * });\n     * ```\n     *\n     * @param status {number} a valid http status code like 200 202 301 500 etc\n     */\n    public httpStatus(status: number): void {\n        this.getConfig('context').turnState.set('httpStatus', status);\n    }\n\n    /**\n     * Set the http response body for this turn.\n     * Use this to define the response value when the platform requires a synchronous response to the incoming webhook.\n     *\n     * Example handling of a /slash command from Slack:\n     * ```javascript\n     * controller.on('slash_command', async(bot, message) => {\n     *  bot.httpBody('This is a reply to the slash command.');\n     * })\n     * ```\n     *\n     * @param body (any) a value that will be returned as the http response body\n     */\n    public httpBody(body: any): void {\n        this.getConfig('context').turnState.set('httpBody', body);\n    }\n}\n"
  },
  {
    "path": "packages/botkit/src/conversation.ts",
    "content": "/**\n * @module botkit\n */\n/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\nimport { Botkit, BotkitMessage } from './core';\nimport { BotWorker } from './botworker';\nimport { BotkitDialogWrapper } from './dialogWrapper';\nimport { Activity, ActivityTypes, TurnContext, MessageFactory, ActionTypes } from 'botbuilder';\nimport { Dialog, DialogContext, DialogReason, PromptValidatorContext, ActivityPrompt, DialogTurnStatus } from 'botbuilder-dialogs';\nimport * as mustache from 'mustache';\nimport * as Debug from 'debug';\n\nconst debug = Debug('botkit:conversation');\n\n/**\n * Definition of the handler functions used to handle .ask and .addQuestion conditions\n */\ninterface BotkitConvoHandler {\n    (answer: string, convo: BotkitDialogWrapper, bot: BotWorker, message: BotkitMessage): Promise<any>;\n}\n\n/**\n * Definition of the trigger pattern passed into .ask or .addQuestion\n */\ninterface BotkitConvoTrigger {\n    type?: string;\n    pattern?: string | RegExp;\n    handler: BotkitConvoHandler;\n    default?: boolean;\n}\n\n/**\n * Template for definiting a BotkitConversation template\n */\ninterface BotkitMessageTemplate {\n    text: ((template: any, vars: any) => string) | string[];\n    action?: string;\n    execute?: {\n        script: string;\n        thread?: string;\n    };\n    quick_replies?: ((template: any, vars: any) => any[]) | any[];\n    attachments?: ((template: any, vars: any) => any[]) | any[];\n    blocks?: ((template: any, vars: any) => any[]) | any[];\n    attachment?: ((template: any, vars: any) => any) | any;\n    attachmentLayout?: string;\n    channelData?: any;\n    collect: {\n        key?: string;\n        options?: BotkitConvoTrigger[];\n    };\n}\n\nexport interface BotkitConversationStep {\n    /**\n     * The number pointing to the current message in the current thread in this dialog's script\n     */\n    index: number;\n    /**\n     * The name of the current thread\n     */\n    thread: string;\n    /**\n     * The length of the current thread\n     */\n    threadLength: number;\n    /**\n     * A pointer to the current dialog state\n     */\n    state: any;\n    /**\n     * A pointer to any options passed into the dialog when it began\n     */\n    options: any;\n    /**\n     * The reason for this step being called\n     */\n    reason: DialogReason;\n    /**\n     * The results of the previous turn\n     */\n    result: any;\n    /**\n     * A pointer directly to state.values\n     */\n    values: any;\n    /**\n     * A function to call when the step is completed.\n     */\n    next: (stepResult) => Promise<any>;\n}\n\n/**\n * An extension on the [BotBuilder Dialog Class](https://docs.microsoft.com/en-us/javascript/api/botbuilder-dialogs/dialog?view=botbuilder-ts-latest) that provides a Botkit-friendly interface for\n * defining and interacting with multi-message dialogs. Dialogs can be constructed using `say()`, `ask()` and other helper methods.\n *\n * ```javascript\n * // define the structure of your dialog...\n * const convo = new BotkitConversation('foo', controller);\n * convo.say('Hello!');\n * convo.ask('What is your name?', async(answer, convo, bot) => {\n *      await bot.say('Your name is ' + answer);\n * });\n * controller.dialogSet.add(convo);\n *\n * // later on, trigger this dialog by its id\n * controller.on('event', async(bot, message) => {\n *  await bot.beginDialog('foo');\n * })\n * ```\n */\nexport class BotkitConversation<O extends object = {}> extends Dialog<O> {\n    /**\n     * A map of every message in the dialog, broken into threads\n     */\n    public script: any; // TODO: define this with typedefs\n\n    private _prompt: string;\n    private _beforeHooks: {};\n    private _afterHooks: { (context: TurnContext, results: any): void }[];\n    private _changeHooks: {};\n    private _controller: Botkit;\n\n    /**\n     * Create a new BotkitConversation object\n     * @param dialogId A unique identifier for this dialog, used to later trigger this dialog\n     * @param controller A pointer to the main Botkit controller\n     */\n    public constructor(dialogId: string, controller: Botkit) {\n        super(dialogId);\n\n        this._beforeHooks = {};\n        this._afterHooks = [];\n        this._changeHooks = {};\n        this.script = {};\n\n        this._controller = controller;\n\n        // Make sure there is a prompt we can use.\n        // TODO: maybe this ends up being managed by Botkit\n        this._prompt = this.id + '_default_prompt';\n        this._controller.dialogSet.add(new ActivityPrompt(\n            this._prompt,\n            (prompt: PromptValidatorContext<Activity>) => Promise.resolve(prompt.recognized.succeeded === true)\n        ));\n\n        return this;\n    }\n\n    /**\n     * Add a non-interactive message to the default thread.\n     * Messages added with `say()` and `addMessage()` will _not_ wait for a response, will be sent one after another without a pause.\n     *\n     * [Learn more about building conversations &rarr;](../conversations.md#build-a-conversation)\n     *\n     * ```javascript\n     * let conversation = new BotkitConversation('welcome', controller);\n     * conversation.say('Hello! Welcome to my app.');\n     * conversation.say('Let us get started...');\n     * ```\n     *\n     * @param message Message template to be sent\n     */\n    public say(message: Partial<BotkitMessageTemplate> | string): BotkitConversation {\n        this.addMessage(message, 'default');\n        return this;\n    }\n\n    /**\n     * An an action to the conversation timeline. This can be used to go to switch threads or end the dialog.\n     *\n     * When provided the name of another thread in the conversation, this will cause the bot to go immediately\n     * to that thread.\n     *\n     * Otherwise, use one of the following keywords:\n     * * `stop`\n     * * `repeat`\n     * * `complete`\n     * * `timeout`\n     *\n     * [Learn more about building conversations &rarr;](../conversations.md#build-a-conversation)\n     *\n     * ```javascript\n     *\n     * // go to a thread called \"next_thread\"\n     * convo.addAction('next_thread');\n     *\n     * // end the conversation and mark as successful\n     * convo.addAction('complete');\n     * ```\n     * @param action An action or thread name\n     * @param thread_name The name of the thread to which this action is added.  Defaults to `default`\n     */\n    public addAction(action: string, thread_name = 'default'): BotkitConversation {\n        this.addMessage({ action: action }, thread_name);\n        return this;\n    }\n\n    /**\n     * Cause the dialog to call a child dialog, wait for it to complete,\n     * then store the results in a variable and resume the parent dialog.\n     * Use this to [combine multiple dialogs into bigger interactions.](../conversations.md#composing-dialogs)\n     *\n     * [Learn more about building conversations &rarr;](../conversations.md#build-a-conversation)\n     * ```javascript\n     * // define a profile collection dialog\n     * let profileDialog = new BotkitConversation('PROFILE_DIALOG', controller);\n     * profileDialog.ask('What is your name?', async(res, convo, bot) => {}, {key: 'name'});\n     * profileDialog.ask('What is your age?', async(res, convo, bot) => {}, {key: 'age'});\n     * profileDialog.ask('What is your location?', async(res, convo, bot) => {}, {key: 'location'});\n     * controller.addDialog(profileDialog);\n     *\n     * let onboard = new BotkitConversation('ONBOARDING', controller);\n     * onboard.say('Hello! It is time to collect your profile data.');\n     * onboard.addChildDialog('PROFILE_DIALOG', 'profile');\n     * onboard.say('Hello, {{vars.profile.name}}! Onboarding is complete.');\n     * ```\n     *\n     * @param dialog_id the id of another dialog\n     * @param key_name the variable name in which to store the results of the child dialog. if not provided, defaults to dialog_id.\n     * @param thread_name the name of a thread to which this call should be added. defaults to 'default'\n     */\n    public addChildDialog(dialog_id: string, key_name?: string, thread_name = 'default'): BotkitConversation {\n        this.addQuestion({\n            action: 'beginDialog',\n            execute: {\n                script: dialog_id\n            }\n        }, [], { key: key_name || dialog_id }, thread_name);\n\n        return this;\n    }\n\n    /**\n     * Cause the current dialog to handoff to another dialog.\n     * The parent dialog will not resume when the child dialog completes. However, the afterDialog event will not fire for the parent dialog until all child dialogs complete.\n     * Use this to [combine multiple dialogs into bigger interactions.](../conversations.md#composing-dialogs)\n     *\n     * [Learn more about building conversations &rarr;](../conversations.md#build-a-conversation)\n     * ```javascript\n     * let parent = new BotkitConversation('parent', controller);\n     * let child = new BotkitConversation('child', controller);\n     * parent.say('Moving on....');\n     * parent.addGotoDialog('child');\n     * ```\n     *\n     * @param dialog_id the id of another dialog\n     * @param thread_name the name of a thread to which this call should be added. defaults to 'default'\n     */\n    public addGotoDialog(dialog_id: string, thread_name = 'default'): BotkitConversation {\n        this.addMessage({\n            action: 'execute_script',\n            execute: {\n                script: dialog_id\n            }\n        }, thread_name);\n\n        return this;\n    }\n\n    /**\n     * Add a message template to a specific thread.\n     * Messages added with `say()` and `addMessage()` will be sent one after another without a pause.\n     *\n     * [Learn more about building conversations &rarr;](../conversations.md#build-a-conversation)\n     * ```javascript\n     * let conversation = new BotkitConversation('welcome', controller);\n     * conversation.say('Hello! Welcome to my app.');\n     * conversation.say('Let us get started...');\n     * // pass in a message with an action that will cause gotoThread to be called...\n     * conversation.addAction('continuation');\n     *\n     * conversation.addMessage('This is a different thread completely', 'continuation');\n     * ```\n     *\n     * @param message Message template to be sent\n     * @param thread_name Name of thread to which message will be added\n     */\n    public addMessage(message: Partial<BotkitMessageTemplate> | string, thread_name: string): BotkitConversation {\n        if (!thread_name) {\n            thread_name = 'default';\n        }\n\n        if (!this.script[thread_name]) {\n            this.script[thread_name] = [];\n        }\n\n        if (typeof (message) === 'string') {\n            message = { text: [message] };\n        }\n\n        this.script[thread_name].push(message);\n\n        return this;\n    }\n\n    /**\n     * Add a question to the default thread.\n     * In addition to a message template, receives either a single handler function to call when an answer is provided,\n     * or an array of handlers paired with trigger patterns. When providing multiple conditions to test, developers may also provide a\n     * handler marked as the default choice.\n     *\n     * [Learn more about building conversations &rarr;](../conversations.md#build-a-conversation)\n     * ```javascript\n     * // ask a question, handle the response with a function\n     * convo.ask('What is your name?', async(response, convo, bot, full_message) => {\n     *  await bot.say('Oh your name is ' + response);\n     * }, {key: 'name'});\n     *\n     * // ask a question, evaluate answer, take conditional action based on response\n     * convo.ask('Do you want to eat a taco?', [\n     *  {\n     *      pattern: 'yes',\n     *      type: 'string',\n     *      handler: async(response_text, convo, bot, full_message) => {\n     *          return await convo.gotoThread('yes_taco');\n     *      }\n     *  },\n     *  {\n     *      pattern: 'no',\n     *      type: 'string',\n     *      handler: async(response_text, convo, bot, full_message) => {\n     *          return await convo.gotoThread('no_taco');\n     *      }\n     *   },\n     *   {\n     *       default: true,\n     *       handler: async(response_text, convo, bot, full_message) => {\n     *           await bot.say('I do not understand your response!');\n     *           // start over!\n     *           return await convo.repeat();\n     *       }\n     *   }\n     * ], {key: 'tacos'});\n     * ```\n     *\n     * @param message a message that will be used as the prompt\n     * @param handlers one or more handler functions defining possible conditional actions based on the response to the question.\n     * @param key name of variable to store response in.\n     */\n    public ask(message: Partial<BotkitMessageTemplate> | string, handlers: BotkitConvoHandler | BotkitConvoTrigger[], key: {key: string} | string | null): BotkitConversation {\n        this.addQuestion(message, handlers, key, 'default');\n        return this;\n    }\n\n    /**\n     * Identical to [ask()](#ask), but accepts the name of a thread to which the question is added.\n     *\n     * [Learn more about building conversations &rarr;](../conversations.md#build-a-conversation)\n     * @param message A message that will be used as the prompt\n     * @param handlers One or more handler functions defining possible conditional actions based on the response to the question\n     * @param key Name of variable to store response in.\n     * @param thread_name Name of thread to which message will be added\n     */\n    public addQuestion(message: Partial<BotkitMessageTemplate> | string, handlers: BotkitConvoHandler | BotkitConvoTrigger[], key: {key: string} | string | null, thread_name: string): BotkitConversation {\n        if (!thread_name) {\n            thread_name = 'default';\n        }\n\n        if (!this.script[thread_name]) {\n            this.script[thread_name] = [];\n        }\n\n        if (typeof (message) === 'string') {\n            message = { text: [message as string] };\n        }\n\n        message.collect = {};\n\n        if (key) {\n            message.collect = {\n                key: typeof (key) === 'string' ? key : key.key\n            };\n        }\n\n        if (Array.isArray(handlers)) {\n            message.collect.options = handlers;\n        } else if (typeof (handlers) === 'function') {\n            message.collect.options = [\n                {\n                    default: true,\n                    handler: handlers\n                }\n            ];\n        } else {\n            throw new Error('Unsupported handlers type: ' + typeof (handlers));\n        }\n\n        // ensure all options have a type field\n        message.collect.options.forEach((o) => { if (!o.type) { o.type = 'string'; } });\n\n        this.script[thread_name].push(message);\n\n        // add a null message where the handlers for the previous message will fire.\n        this.script[thread_name].push({ action: 'next' });\n\n        return this;\n    }\n\n    /**\n     * Register a handler function that will fire before a given thread begins.\n     * Use this hook to set variables, call APIs, or change the flow of the conversation using `convo.gotoThread`\n     *\n     * ```javascript\n     * convo.addMessage('This is the foo thread: var == {{vars.foo}}', 'foo');\n     * convo.before('foo', async(convo, bot) => {\n     *  // set a variable here that can be used in the message template\n     *  convo.setVar('foo','THIS IS FOO');\n     *\n     * });\n     * ```\n     *\n     * @param thread_name A valid thread defined in this conversation\n     * @param handler A handler function in the form async(convo, bot) => { ... }\n     */\n    public before(thread_name: string, handler: (convo: BotkitDialogWrapper, bot: BotWorker) => Promise<any>): void {\n        if (!this._beforeHooks[thread_name]) {\n            this._beforeHooks[thread_name] = [];\n        }\n\n        this._beforeHooks[thread_name].push(handler);\n    }\n\n    /**\n     * This private method is called before a thread begins, and causes any bound handler functions to be executed.\n     * @param thread_name the thread about to begin\n     * @param dc the current DialogContext\n     * @param step the current step object\n     */\n    private async runBefore(thread_name: string, dc: DialogContext, step: BotkitConversationStep): Promise<void> {\n        debug('Before:', this.id, thread_name);\n\n        if (this._beforeHooks[thread_name]) {\n            // spawn a bot instance so devs can use API or other stuff as necessary\n            const bot = await this._controller.spawn(dc);\n\n            // create a convo controller object\n            const convo = new BotkitDialogWrapper(dc, step);\n\n            for (let h = 0; h < this._beforeHooks[thread_name].length; h++) {\n                const handler = this._beforeHooks[thread_name][h];\n                await handler.call(this, convo, bot);\n            }\n        }\n    }\n\n    /**\n     * Bind a function to run after the dialog has completed.\n     * The first parameter to the handler will include a hash of all variables set and values collected from the user during the conversation.\n     * The second parameter to the handler is a BotWorker object that can be used to start new dialogs or take other actions.\n     *\n     * [Learn more about handling end of conversation](../conversations.md#handling-end-of-conversation)\n     * ```javascript\n     * let convo = new BotkitConversation(MY_CONVO, controller);\n     * convo.ask('What is your name?', [], 'name');\n     * convo.ask('What is your age?', [], 'age');\n     * convo.ask('What is your favorite color?', [], 'color');\n     * convo.after(async(results, bot) => {\n     *\n     *      // handle results.name, results.age, results.color\n     *\n     * });\n     * controller.addDialog(convo);\n     * ```\n     *\n     * @param handler in the form async(results, bot) { ... }\n     */\n    public after(handler: (results: any, bot: BotWorker) => void): void {\n        this._afterHooks.push(handler);\n    }\n\n    /**\n     * This private method is called at the end of the conversation, and causes any bound handler functions to be executed.\n     * @param context the current dialog context\n     * @param results an object containing the final results of the dialog\n     */\n    private async runAfter(context: DialogContext, results: any): Promise<void> {\n        debug('After:', this.id);\n        if (this._afterHooks.length) {\n            const bot = await this._controller.spawn(context);\n            for (let h = 0; h < this._afterHooks.length; h++) {\n                const handler = this._afterHooks[h];\n                await handler.call(this, results, bot);\n            }\n        }\n    }\n\n    /**\n     * Bind a function to run whenever a user answers a specific question.  Can be used to validate input and take conditional actions.\n     *\n     * ```javascript\n     * convo.ask('What is your name?', [], 'name');\n     * convo.onChange('name', async(response, convo, bot) => {\n     *\n     *  // user changed their name!\n     *  // do something...\n     *\n     * });\n     * ```\n     * @param variable name of the variable to watch for changes\n     * @param handler a handler function that will fire whenever a user's response is used to change the value of the watched variable\n     */\n    public onChange(variable: string, handler: (response, convo, bot) => Promise<any>): void {\n        if (!this._changeHooks[variable]) {\n            this._changeHooks[variable] = [];\n        }\n\n        this._changeHooks[variable].push(handler);\n    }\n\n    /**\n     * This private method is responsible for firing any bound onChange handlers when a variable changes\n     * @param variable the name of the variable that is changing\n     * @param value the new value of the variable\n     * @param dc the current DialogContext\n     * @param step the current step object\n     */\n    private async runOnChange(variable: string, value: any, dc: DialogContext, step: BotkitConversationStep): Promise<void> {\n        debug('OnChange:', this.id, variable);\n\n        if (this._changeHooks[variable] && this._changeHooks[variable].length) {\n            // spawn a bot instance so devs can use API or other stuff as necessary\n            const bot = await this._controller.spawn(dc);\n\n            // create a convo controller object\n            const convo = new BotkitDialogWrapper(dc, step);\n\n            for (let h = 0; h < this._changeHooks[variable].length; h++) {\n                const handler = this._changeHooks[variable][h];\n                await handler.call(this, value, convo, bot);\n            }\n        }\n    }\n\n    /**\n     * Called automatically when a dialog begins. Do not call this directly!\n     * @ignore\n     * @param dc the current DialogContext\n     * @param options an object containing initialization parameters passed to the dialog. may include `thread` which will cause the dialog to begin with that thread instead of the `default` thread.\n     */\n    public async beginDialog(dc: DialogContext, options: any): Promise<any> {\n        // Initialize the state\n        const state = dc.activeDialog.state;\n        state.options = options || {};\n        state.values = { ...options };\n\n        // Run the first step\n        return await this.runStep(dc, 0, state.options.thread || 'default', DialogReason.beginCalled);\n    }\n\n    /**\n     * Called automatically when an already active dialog is continued. Do not call this directly!\n     * @ignore\n     * @param dc the current DialogContext\n     */\n    public async continueDialog(dc: DialogContext): Promise<any> {\n        // Don't do anything for non-message activities\n        if (dc.context.activity.type !== ActivityTypes.Message) {\n            return Dialog.EndOfTurn;\n        }\n\n        // Run next step with the message text as the result.\n        return await this.resumeDialog(dc, DialogReason.continueCalled, dc.context.activity);\n    }\n\n    /**\n     * Called automatically when a dialog moves forward a step. Do not call this directly!\n     * @ignore\n     * @param dc The current DialogContext\n     * @param reason Reason for resuming the dialog\n     * @param result Result of previous step\n     */\n    public async resumeDialog(dc, reason, result): Promise<any> {\n        // Increment step index and run step\n        if (dc.activeDialog) {\n            const state = dc.activeDialog.state;\n            return await this.runStep(dc, state.stepIndex + 1, state.thread || 'default', reason, result);\n        } else {\n            return Dialog.EndOfTurn;\n        }\n    }\n\n    /**\n     * Called automatically to process the turn, interpret the script, and take any necessary actions based on that script. Do not call this directly!\n     * @ignore\n     * @param dc The current dialog context\n     * @param step The current step object\n     */\n    private async onStep(dc, step): Promise<any> {\n        // Let's interpret the current line of the script.\n        const thread = this.script[step.thread];\n\n        if (!thread) {\n            throw new Error(`Thread '${ step.thread }' not found, did you add any messages to it?`);\n        }\n\n        // Capture the previous step value if there previous line included a prompt\n        const previous = (step.index >= 1) ? thread[step.index - 1] : null;\n        if (step.result && previous && previous.collect) {\n            if (previous.collect.key) {\n                // capture before values\n                const index = step.index;\n                const thread_name = step.thread;\n\n                // capture the user input value into the array\n                if (step.values[previous.collect.key] && previous.collect.multiple) {\n                    step.values[previous.collect.key] = [step.values[previous.collect.key], step.result].join('\\n');\n                } else {\n                    step.values[previous.collect.key] = step.result;\n                }\n\n                // run onChange handlers\n                await this.runOnChange(previous.collect.key, step.result, dc, step);\n\n                // did we just change threads? if so, restart this turn\n                if (index !== step.index || thread_name !== step.thread) {\n                    return await this.runStep(dc, step.index, step.thread, DialogReason.nextCalled);\n                }\n            }\n\n            // handle conditions of previous step\n            if (previous.collect.options) {\n                const paths = previous.collect.options.filter((option) => { return !option.default === true; });\n                const default_path = previous.collect.options.filter((option) => { return option.default === true; })[0];\n                let path = null;\n\n                for (let p = 0; p < paths.length; p++) {\n                    const condition = paths[p];\n                    let test;\n                    if (condition.type === 'string') {\n                        test = new RegExp(condition.pattern, 'i');\n                    } else if (condition.type === 'regex') {\n                        test = new RegExp(condition.pattern, 'i');\n                    }\n                    // TODO: Allow functions to be passed in as patterns\n                    // ie async(test) => Promise<boolean>\n\n                    if (step.result && typeof (step.result) === 'string' && step.result.match(test)) {\n                        path = condition;\n                        break;\n                    }\n                }\n\n                // take default path if one is set\n                if (!path) {\n                    path = default_path;\n                }\n\n                if (path) {\n                    if (path.action !== 'wait' && previous.collect && previous.collect.multiple) {\n                        // TODO: remove the final line of input\n                        // since this would represent the \"end\" message and probably not part of the input\n                    }\n\n                    const res = await this.handleAction(path, dc, step);\n                    if (res !== false) {\n                        return res;\n                    }\n                }\n            }\n        }\n\n        // was the dialog canceled during the last action?\n        if (!dc.activeDialog) {\n            return await this.end(dc);\n        }\n\n        // Handle the current step\n        if (step.index < thread.length) {\n            const line = thread[step.index];\n\n            // If a prompt is defined in the script, use dc.prompt to call it.\n            // This prompt must be a valid dialog defined somewhere in your code!\n            if (line.collect && line.action !== 'beginDialog') {\n                try {\n                    return await dc.prompt(this._prompt, await this.makeOutgoing(dc, line, step.values));\n                } catch (err) {\n                    console.error(err);\n                    await dc.context.sendActivity(`Failed to start prompt ${ this._prompt }`);\n                    return await step.next();\n                }\n                // If there's nothing but text, send it!\n                // This could be extended to include cards and other activity attributes.\n            } else {\n                // if there is text, attachments, or any channel data fields at all...\n                if (line.type || line.text || line.attachments || line.attachment || line.blocks || (line.channelData && Object.keys(line.channelData).length)) {\n                    await dc.context.sendActivity(await this.makeOutgoing(dc, line, step.values));\n                } else if (!line.action) {\n                    console.error('Dialog contains invalid message', line);\n                }\n\n                if (line.action) {\n                    const res = await this.handleAction(line, dc, step);\n                    if (res !== false) {\n                        return res;\n                    }\n                }\n\n                return await step.next();\n            }\n        } else {\n            // End of script so just return to parent\n            return await this.end(dc);\n        }\n    }\n\n    /**\n     * Run a dialog step, based on the index and thread_name passed in.\n     * @param dc The current DialogContext\n     * @param index The index of the current step\n     * @param thread_name The name of the current thread\n     * @param reason The reason given for running this step\n     * @param result The result of the previous turn if any\n     */\n    private async runStep(dc: DialogContext, index: number, thread_name: string, reason: DialogReason, result?: any): Promise<any> {\n        // Update the step index\n        const state = dc.activeDialog.state;\n        state.stepIndex = index;\n        state.thread = thread_name;\n        // Create step context\n        const nextCalled = false;\n        const step = {\n            index: index,\n            threadLength: this.script[thread_name].length,\n            thread: thread_name,\n            state: state,\n            options: state.options,\n            reason: reason,\n            result: result && result.text ? result.text : result,\n            resultObject: result,\n            values: state.values,\n            next: async (stepResult): Promise<any> => {\n                if (nextCalled) {\n                    throw new Error(`ScriptedStepContext.next(): method already called for dialog and step '${ this.id }[${ index }]'.`);\n                }\n                return await this.resumeDialog(dc, DialogReason.nextCalled, stepResult);\n            }\n        };\n\n        // did we just start a new thread?\n        // if so, run the before stuff.\n        if (index === 0) {\n            await this.runBefore(step.thread, dc, step);\n\n            // did we just change threads? if so, restart\n            if (index !== step.index || thread_name !== step.thread) {\n                return await this.runStep(dc, step.index, step.thread, DialogReason.nextCalled); // , step.values);\n            }\n        }\n\n        // Execute step\n        const res = await this.onStep(dc, step);\n\n        return res;\n    }\n\n    /**\n     * Automatically called when the the dialog ends and causes any handlers bound using `after()` to fire. Do not call this directly!\n     * @ignore\n     * @param dc The current DialogContext\n     * @param value The final value collected by the dialog.\n     */\n    public async end(dc: DialogContext): Promise<DialogTurnStatus> {\n        // TODO: may have to move these around\n        // shallow copy todo: may need deep copy\n        // protect against canceled dialog.\n        if (dc.activeDialog && dc.activeDialog.state) {\n            const result = {\n                ...dc.activeDialog.state.values\n            };\n            await dc.endDialog(result);\n            await this.runAfter(dc, result);\n        } else {\n            await dc.endDialog();\n        }\n\n        return DialogTurnStatus.complete;\n    }\n\n    /**\n     * Translates a line from the dialog script into an Activity. Responsible for doing token replacement.\n     * @param line a message template from the script\n     * @param vars an object containing key/value pairs used to do token replacement on fields in the message template\n     */\n    private async makeOutgoing(dc: DialogContext, line: any, vars: any): Promise<any> {\n        let outgoing;\n        let text = '';\n\n        // if the text is just a string, use it.\n        // otherwise, if it is an array, pick a random element\n        if (line.text && typeof (line.text) === 'string') {\n            text = line.text;\n        // If text is a function, call the function to get the actual text value.\n        } else if (line.text && typeof (line.text) === 'function') {\n            text = await line.text(line, vars);\n        } else if (Array.isArray(line.text)) {\n            text = line.text[Math.floor(Math.random() * line.text.length)];\n        }\n\n        /*******************************************************************************************************************/\n        // use Bot Framework's message factory to construct the initial object.\n        if (line.quick_replies && typeof (line.quick_replies) !== 'function') {\n            outgoing = MessageFactory.suggestedActions(line.quick_replies.map((reply) => { return { type: ActionTypes.PostBack, title: reply.title, text: reply.payload, displayText: reply.title, value: reply.payload }; }), text);\n        } else {\n            outgoing = MessageFactory.text(text);\n        }\n\n        outgoing.channelData = outgoing.channelData ? outgoing.channelData : {};\n        if (line.attachmentLayout) {\n            outgoing.attachmentLayout = line.attachmentLayout;\n        }\n        /*******************************************************************************************************************/\n        // allow dynamic generation of quick replies and/or attachments\n        if (typeof (line.quick_replies) === 'function') {\n            // set both formats of quick replies\n            outgoing.channelData.quick_replies = await line.quick_replies(line, vars);\n            outgoing.suggestedActions = { actions: outgoing.channelData.quick_replies.map((reply) => { return { type: ActionTypes.PostBack, title: reply.title, text: reply.payload, displayText: reply.title, value: reply.payload }; }) };\n        }\n        if (typeof (line.attachment) === 'function') {\n            outgoing.channelData.attachment = await line.attachment(line, vars);\n        }\n        if (typeof (line.attachments) === 'function') {\n            // set both locations for attachments\n            outgoing.attachments = outgoing.channelData.attachments = await line.attachments(line, vars);\n        }\n        if (typeof (line.blocks) === 'function') {\n            outgoing.channelData.blocks = await line.blocks(line, vars);\n        }\n\n        /*******************************************************************************************************************/\n        // Map some fields into the appropriate places for processing by Botkit/ Bot Framework\n\n        // Quick replies are used by Facebook and Web adapters, but in a different way than they are for Bot Framework.\n        // In order to make this as easy as possible, copy these fields for the developer into channelData.\n        if (line.quick_replies && typeof (line.quick_replies) !== 'function') {\n            outgoing.channelData.quick_replies = JSON.parse(JSON.stringify(line.quick_replies));\n        }\n\n        // Similarly, attachment and blocks fields are platform specific.\n        // handle slack Block attachments\n        if (line.blocks && typeof (line.blocks) !== 'function') {\n            outgoing.channelData.blocks = JSON.parse(JSON.stringify(line.blocks));\n        }\n\n        // handle facebook attachments.\n        if (line.attachment && typeof (line.attachment) !== 'function') {\n            outgoing.channelData.attachment = JSON.parse(JSON.stringify(line.attachment));\n        }\n\n        // set the type\n        if (line.type) {\n            outgoing.type = JSON.parse(JSON.stringify(line.type));\n        }\n\n        // copy all the values in channelData fields\n        if (line.channelData && Object.keys(line.channelData).length > 0) {\n            const channelDataParsed = this.parseTemplatesRecursive(JSON.parse(JSON.stringify(line.channelData)), vars);\n\n            outgoing.channelData = {\n                ...outgoing.channelData,\n                ...channelDataParsed\n            };\n        }\n\n        /*******************************************************************************************************************/\n        // Handle template token replacements\n        if (outgoing.text) {\n            outgoing.text = mustache.render(outgoing.text, { vars: vars });\n        }\n\n        // process templates in native botframework attachments and/or slack attachments\n        if (line.attachments && typeof (line.attachments) !== 'function') {\n            outgoing.attachments = this.parseTemplatesRecursive(JSON.parse(JSON.stringify(line.attachments)), vars);\n        }\n\n        // process templates in slack attachments in channelData\n        if (outgoing.channelData.attachments) {\n            outgoing.channelData.attachments = this.parseTemplatesRecursive(outgoing.channelData.attachments, vars);\n        }\n        if (outgoing.channelData.blocks) {\n            outgoing.channelData.blocks = this.parseTemplatesRecursive(outgoing.channelData.blocks, vars);\n        }\n\n        // process templates in facebook attachments\n        if (outgoing.channelData.attachment) {\n            outgoing.channelData.attachment = this.parseTemplatesRecursive(outgoing.channelData.attachment, vars);\n        }\n\n        // process templates in quick replies\n        if (outgoing.channelData.quick_replies) {\n            outgoing.channelData.quick_replies = this.parseTemplatesRecursive(outgoing.channelData.quick_replies, vars);\n        }\n        // process templates in quick replies\n        if (outgoing.suggestedActions) {\n            outgoing.suggestedActions = this.parseTemplatesRecursive(outgoing.suggestedActions, vars);\n        }\n\n        return new Promise((resolve, reject) => {\n            // run the outgoing message through the Botkit send middleware\n            this._controller.spawn(dc).then((bot) => {\n                this._controller.middleware.send.run(bot, outgoing, (err, bot, outgoing) => {\n                    if (err) {\n                        reject(err);\n                    } else {\n                        resolve(outgoing);\n                    }\n                });\n            }).catch(reject);\n        });\n    }\n\n    /**\n     * Responsible for doing token replacements recursively in attachments and other multi-field properties of the message.\n     * @param attachments some object or array containing values for which token replacements should be made.\n     * @param vars an object defining key/value pairs used for the token replacements\n     */\n    private parseTemplatesRecursive(attachments: any, vars: any): any {\n        if (attachments && attachments.length) {\n            for (let a = 0; a < attachments.length; a++) {\n                for (const key in attachments[a]) {\n                    if (typeof (attachments[a][key]) === 'string') {\n                        attachments[a][key] = mustache.render(attachments[a][key], { vars: vars });\n                    } else {\n                        attachments[a][key] = this.parseTemplatesRecursive(attachments[a][key], vars);\n                    }\n                }\n            }\n        } else {\n            for (const x in attachments) {\n                if (typeof (attachments[x]) === 'string') {\n                    attachments[x] = mustache.render(attachments[x], { vars: vars });\n                } else {\n                    attachments[x] = this.parseTemplatesRecursive(attachments[x], vars);\n                }\n            }\n        }\n\n        return attachments;\n    }\n\n    /**\n     * Handle the scripted \"gotothread\" action - requires an additional call to runStep.\n     * @param thread The name of the thread to jump to\n     * @param dc The current DialogContext\n     * @param step The current step object\n     */\n    private async gotoThreadAction(thread: string, dc: DialogContext, step: BotkitConversationStep): Promise<any> {\n        step.thread = thread;\n        step.index = 0;\n\n        return await this.runStep(dc, step.index, step.thread, DialogReason.nextCalled, step.values);\n    }\n\n    /**\n     * Accepts a Botkit script action, and performs that action\n     * @param path A conditional path in the form {action: 'some action', handler?: some handler function, maybe_other_fields}\n     * @param dc The current DialogContext\n     * @param step The current stpe object\n     */\n    private async handleAction(path, dc, step): Promise<any> {\n        let worker = null;\n        if (path.handler) {\n            const index = step.index;\n            const thread_name = step.thread;\n            const result = step.result;\n            const response = result == null ? null : (result.text || (typeof (result) === 'string' ? result : null));\n\n            // spawn a bot instance so devs can use API or other stuff as necessary\n            const bot = await this._controller.spawn(dc);\n\n            // create a convo controller object\n            const convo = new BotkitDialogWrapper(dc, step);\n\n            const activedialog = dc.activeDialog.id;\n\n            await path.handler.call(this, response, convo, bot, dc.context.turnState.get('botkitMessage') || dc.context.activity);\n\n            if (!dc.activeDialog) {\n                return false;\n            }\n\n            // did we change dialogs? if so, return an endofturn because the new dialog has taken over.\n            if (activedialog !== dc.activeDialog.id) {\n                return Dialog.EndOfTurn;\n            }\n\n            // did we just change threads? if so, restart this turn\n            if (index !== step.index || thread_name !== step.thread) {\n                return await this.runStep(dc, step.index, step.thread, DialogReason.nextCalled, null);\n            }\n\n            return false;\n        }\n\n        switch (path.action) {\n        case 'next':\n            // noop\n            break;\n        case 'complete':\n            step.values._status = 'completed';\n            return await this.end(dc);\n        case 'stop':\n            step.values._status = 'canceled';\n            return await this.end(dc);\n        case 'timeout':\n            step.values._status = 'timeout';\n            return await this.end(dc);\n        case 'execute_script':\n            worker = await this._controller.spawn(dc);\n\n            await worker.replaceDialog(path.execute.script, {\n                thread: path.execute.thread,\n                ...step.values\n            });\n\n            return { status: DialogTurnStatus.waiting };\n        case 'beginDialog':\n            worker = await this._controller.spawn(dc);\n\n            await worker.beginDialog(path.execute.script, {\n                thread: path.execute.thread,\n                ...step.values\n            });\n            return { status: DialogTurnStatus.waiting };\n        case 'repeat':\n            return await this.runStep(dc, step.index - 1, step.thread, DialogReason.nextCalled);\n        case 'wait':\n            // reset the state so we're still on this step.\n            step.state.stepIndex = step.index - 1;\n            // send a waiting status\n            return { status: DialogTurnStatus.waiting };\n        default:\n            // the default behavior for unknown action in botkit is to gotothread\n            if (this.script[path.action]) {\n                return await this.gotoThreadAction(path.action, dc, step);\n            }\n            console.warn('NOT SURE WHAT TO DO WITH THIS!!', path);\n            break;\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "packages/botkit/src/conversationState.ts",
    "content": "/**\n * @module botkit\n */\n/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\nimport { Activity, ConversationState, TurnContext } from 'botbuilder';\n\n/**\n * A customized version of [ConversationState](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/conversationstate?view=botbuilder-ts-latest) that  overide the [getStorageKey](#getStorageKey) method to create a more complex key value.\n * This allows Botkit to automatically track conversation state in scenarios where multiple users are present in a single channel,\n * or when threads or sub-channels parent channel that would normally collide based on the information defined in the conversation address field.\n * Note: This is used automatically inside Botkit and developers should not need to directly interact with it.\n * @ignore\n */\nexport class BotkitConversationState extends ConversationState {\n    public getStorageKey(context: TurnContext): string | undefined {\n        const activity: Activity = context.activity;\n        const channelId: string = activity.channelId;\n        if (!activity.conversation || !activity.conversation.id) {\n            throw new Error('missing activity.conversation');\n        }\n\n        // create a combo key by sorting all the fields in the conversation address and combining them all\n        // mix in user id as well, because conversations are between the bot and a single user\n        const conversationId: string = Object.keys(activity.conversation).filter((key) => { return key !== 'properties'; }).sort().map((key) => activity.conversation[key]).filter((val) => val !== '' && val !== null && typeof val !== 'undefined').join('-') + '-' + activity.from.id;\n\n        if (!channelId) {\n            throw new Error('missing activity.channelId');\n        }\n\n        if (!conversationId) {\n            throw new Error('missing activity.conversation.id');\n        }\n\n        // eslint-disable-next-line @typescript-eslint/ban-ts-ignore\n        // @ts-ignore namespace is technically private\n        return `${ channelId }/conversations/${ conversationId }/${ this.namespace }`;\n    }\n}\n"
  },
  {
    "path": "packages/botkit/src/core.ts",
    "content": "/**\n * @module botkit\n */\n/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\nimport { Activity, MemoryStorage, Storage, ConversationReference, TurnContext, BotAdapter } from 'botbuilder';\nimport { Dialog, DialogContext, DialogSet, DialogTurnStatus, WaterfallDialog } from 'botbuilder-dialogs';\nimport { BotkitBotFrameworkAdapter } from './adapter';\nimport { BotWorker } from './botworker';\nimport { BotkitConversationState } from './conversationState';\nimport * as path from 'path';\nimport * as http from 'http';\nimport * as express from 'express';\nimport * as bodyParser from 'body-parser';\nimport * as Ware from 'ware';\nimport * as fs from 'fs';\nimport * as Debug from 'debug';\n\nconst debug = Debug('botkit');\n\n/**\n * Defines the options used when instantiating Botkit to create the main app controller with `new Botkit(options)`\n */\nexport interface BotkitConfiguration {\n    /**\n     * Path used to create incoming webhook URI.  Defaults to `/api/messages`\n     */\n    webhook_uri?: string;\n\n    /**\n     * Name of the dialogState property in the ConversationState that will be used to automatically track the dialog state. Defaults to `dialogState`.\n     */\n    dialogStateProperty?: string;\n\n    /**\n     * A fully configured BotBuilder Adapter, such as `botbuilder-adapter-slack` or `botbuilder-adapter-web`\n     * The adapter is responsible for translating platform-specific messages into the format understood by Botkit and BotBuilder.\n     */\n    adapter?: any;\n\n    /**\n     * If using the BotFramework service, options included in `adapterConfig` will be passed to the new Adapter when created internally.\n     * See [BotFrameworkAdapterSettings](https://docs.microsoft.com/en-us/javascript/api/botbuilder/botframeworkadaptersettings?view=azure-node-latest&viewFallbackFrom=botbuilder-ts-latest).\n     */\n    adapterConfig?: {[key: string]: any}; // object with stuff in it\n\n    /**\n     * An instance of Express used to define web endpoints.  If not specified, one will be created internally.\n     * Note: only use your own Express if you absolutely must for some reason. Otherwise, use `controller.webserver`\n     */\n    webserver?: any;\n\n    /**\n     * An array of middlewares that will be automatically bound to the webserver.\n     * Should be in the form (req, res, next) => {}\n     */\n    webserver_middlewares?: any[];\n\n    /**\n     * A Storage interface compatible with [this specification](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/storage?view=botbuilder-ts-latest)\n     * Defaults to the ephemeral [MemoryStorage](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/memorystorage?view=botbuilder-ts-latest) implementation.\n     */\n    storage?: Storage;\n\n    /**\n     * Disable webserver. If true, Botkit will not create a webserver or expose any webhook endpoints automatically. Defaults to false.\n     * For an example of how to use your own Express, [see this sample code](https://github.com/howdyai/botkit/blob/main/packages/testbot/custom_express.js).\n     */\n    disable_webserver?: boolean;\n\n    /**\n     * Disable messages normally sent to the console during startup.\n     */\n    disable_console?: boolean;\n\n    /**\n     * Limit of the size of incoming JSON payloads parsed by the Express bodyParser. Defaults to '100kb'\n     */\n    jsonLimit?: string;\n\n    /**\n     * Limit of the size of incoming URL encoded payloads parsed by the Express bodyParser. Defaults to '100kb'\n     */\n    urlEncodedLimit?: string;\n\n}\n\n/**\n * Defines the expected form of a message or event object being handled by Botkit.\n * Will also contain any additional fields including in the incoming payload.\n */\nexport interface BotkitMessage {\n    /**\n     * The type of event, in most cases defined by the messaging channel or adapter\n     */\n    type: string;\n\n    /**\n     * Text of the message sent by the user (or primary value in case of button click)\n     */\n    text?: string;\n\n    /**\n     * Any value field received from the platform\n     */\n    value?: string;\n\n    /**\n     * Unique identifier of user who sent the message. Typically contains the platform specific user id.\n     */\n    user: string;\n\n    /**\n     * Unique identifier of the room/channel/space in which the message was sent. Typically contains the platform specific designator for that channel.\n     */\n    channel: string;\n\n    /**\n     * A full [ConversationReference](https://docs.microsoft.com/en-us/javascript/api/botframework-schema/conversationreference?view=botbuilder-ts-latest) object that defines the address of the message and all information necessary to send messages back to the originating location.\n     * Can be stored for later use, and used with [bot.changeContext()](#changeContext) to send proactive messages.\n     */\n    reference: ConversationReference;\n\n    /**\n     * The original incoming [BotBuilder Activity](https://docs.microsoft.com/en-us/javascript/api/botframework-schema/activity?view=botbuilder-ts-latest) object as created by the adapter.\n     */\n    incoming_message: Activity;\n\n    /**\n     * Any additional fields found in the incoming payload from the messaging platform.\n     */\n    [key: string]: any;\n}\n\n/**\n * A handler function passed into `hears()` or `on()` that receives a [BotWorker](#botworker) instance and a [BotkitMessage](#botkitmessage).  Should be defined as an async function and/or return a Promise.\n *\n * The form of these handlers should be:\n * ```javascript\n * async (bot, message) => {\n * // stuff.\n * }\n * ```\n *\n * For example:\n * ```javascript\n * controller.on('event', async(bot, message) => {\n *  // do somethign using bot and message like...\n *  await bot.reply(message,'Received an event.');\n * });\n * ```\n */\nexport interface BotkitHandler {\n    (bot: BotWorker, message: BotkitMessage): Promise<any>;\n}\n\n/**\n * Defines a trigger, including the type, pattern and handler function to fire if triggered.\n */\ninterface BotkitTrigger {\n    /**\n     * string, regexp or function\n     */\n    type: string;\n    pattern: string | RegExp | { (message: BotkitMessage): Promise<boolean> };\n    handler: BotkitHandler;\n}\n\n/**\n * An interface for plugins that can contain multiple middlewares as well as an init function.\n */\nexport interface BotkitPlugin {\n    name: string;\n    middlewares?: {\n        [key: string]: any[];\n    };\n    init?: (botkit: Botkit) => void;\n    [key: string]: any; // allow arbitrary additional fields to be added.\n}\n\n/**\n * Create a new instance of Botkit to define the controller for a conversational app.\n * To connect Botkit to a chat platform, pass in a fully configured `adapter`.\n * If one is not specified, Botkit will expose an adapter for the Microsoft Bot Framework.\n */\nexport class Botkit {\n    /**\n     * _config contains the options passed to the constructor.\n     * this property should never be accessed directly - use `getConfig()` instead.\n     */\n    private _config: BotkitConfiguration;\n\n    /**\n     * _events contains the list of all events for which Botkit has registered handlers.\n     * Each key in this object points to an array of handler functions bound to that event.\n     */\n    private _events: {\n        [key: string]: BotkitHandler[];\n    } = {};\n\n    /**\n     * _triggers contains a list of trigger patterns htat Botkit will watch for.\n     * Each key in this object points to an array of patterns and their associated handlers.\n     * Each key represents an event type.\n     */\n    private _triggers: {\n        [key: string]: BotkitTrigger[];\n    } = {};\n\n    /**\n     * _interrupts contains a list of trigger patterns htat Botkit will watch for and fire BEFORE firing any normal triggers.\n     * Each key in this object points to an array of patterns and their associated handlers.\n     * Each key represents an event type.\n     */\n    private _interrupts: {\n        [key: string]: BotkitTrigger[];\n    } = {};\n\n    /**\n     * conversationState is used to track and persist the state of any ongoing conversations.\n     * See https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-howto-v4-state?view=azure-bot-service-4.0&tabs=javascript\n     */\n    private conversationState: BotkitConversationState;\n\n    /**\n     * _deps contains a list of all dependencies that Botkit must load before being ready to operate.\n     * see addDep(), completeDep() and ready()\n     */\n    private _deps: {};\n\n    /**\n     * contains an array of functions that will fire when Botkit has completely booted.\n     */\n    private _bootCompleteHandlers: { (): void }[];\n\n    /**\n     * The current version of Botkit Core\n     */\n    public version: string = require('../package.json').version;\n\n    /**\n     * Middleware endpoints available for plugins and features to extend Botkit.\n     * Endpoints available are: spawn, ingest, receive, send.\n     *\n     * To bind a middleware function to Botkit:\n     * ```javascript\n     * controller.middleware.receive.use(function(bot, message, next) {\n     *\n     *  // do something with bot or message\n     *\n     *  // always call next, or your bot will freeze!\n     *  next();\n     * });\n     * ```\n     */\n    public middleware = {\n        spawn: new Ware(),\n        ingest: new Ware(),\n        send: new Ware(),\n        receive: new Ware(),\n        interpret: new Ware()\n    }\n\n    /**\n     * A list of all the installed plugins.\n     */\n    private plugin_list: string[];\n\n    /**\n     * A place where plugins can extend the controller object with new methods\n     */\n    private _plugins: {\n        [key: string]: any;\n    };\n\n    /**\n     * a BotBuilder storage driver - defaults to MemoryStorage\n     */\n    public storage: Storage;\n\n    /**\n     * An Express webserver\n     */\n    public webserver: any;\n\n    /**\n     * A direct reference to the underlying HTTP server object\n     */\n    public http: any;\n\n    /**\n     * Any BotBuilder-compatible adapter - defaults to a [BotFrameworkAdapter](https://docs.microsoft.com/en-us/javascript/api/botbuilder/botframeworkadapter?view=botbuilder-ts-latest)\n     */\n    public adapter: any; // The base type of this is BotAdapter, but TypeScript doesn't like that we call adapter.processActivity since it is not part of the base class...\n\n    /**\n     * A BotBuilder DialogSet that serves as the top level dialog container for the Botkit app\n     */\n    public dialogSet: DialogSet;\n\n    /**\n     * The path of the main Botkit SDK, used to generate relative paths\n     */\n    public PATH: string;\n\n    /**\n     * Indicates whether or not Botkit has fully booted.\n     */\n    private booted: boolean;\n\n    /**\n     * Create a new Botkit instance and optionally specify a platform-specific adapter.\n     * By default, Botkit will create a [BotFrameworkAdapter](https://docs.microsoft.com/en-us/javascript/api/botbuilder/botframeworkadapter?view=botbuilder-ts-latest).\n     *\n     * ```javascript\n     * const controller = new Botkit({\n     *      adapter: some_adapter,\n     *      webhook_uri: '/api/messages',\n     * });\n     *\n     * controller.on('message', async(bot, message) => {\n     *      // do something!\n     * });\n     * ```\n     *\n     * @param config Configuration for this instance of Botkit\n     */\n    public constructor(config: BotkitConfiguration) {\n        // Set the path where Botkit's core lib is found.\n        this.PATH = __dirname;\n\n        this._config = {\n            webhook_uri: '/api/messages',\n            dialogStateProperty: 'dialogState',\n            disable_webserver: false,\n            jsonLimit: '100kb',\n            urlEncodedLimit: '100kb',\n            ...config\n        };\n\n        // The _deps object contains references to dependencies that may take time to load and be ready.\n        // new _deps are defined in the constructor.\n        // when all _deps are true, the controller.ready function runs and executes all functions in order.\n        this._deps = {};\n        this._bootCompleteHandlers = [];\n        this.booted = false;\n        this.addDep('booted');\n\n        debug('Booting Botkit ', this.version);\n\n        if (!this._config.storage) {\n            // Set up temporary storage for dialog state.\n            this.storage = new MemoryStorage();\n            if (this._config.disable_console !== true) {\n                console.warn('** Your bot is using memory storage and will forget everything when it reboots!');\n                console.warn('** To preserve dialog state, specify a storage adapter in your Botkit config:');\n                console.warn('** const controller = new Botkit({storage: myStorageAdapter});');\n            }\n        } else {\n            this.storage = this._config.storage;\n        }\n\n        this.conversationState = new BotkitConversationState(this.storage);\n\n        const dialogState = this.conversationState.createProperty(this.getConfig('dialogStateProperty'));\n\n        this.dialogSet = new DialogSet(dialogState);\n\n        if (this._config.disable_webserver !== true) {\n            if (!this._config.webserver) {\n                // Create HTTP server\n                this.addDep('webserver');\n\n                this.webserver = express();\n\n                // capture raw body\n                this.webserver.use((req, res, next) => {\n                    req.rawBody = '';\n                    req.on('data', function(chunk) {\n                        req.rawBody += chunk;\n                    });\n                    next();\n                });\n\n                this.webserver.use(bodyParser.json({ limit: this._config.jsonLimit }));\n                this.webserver.use(bodyParser.urlencoded({ limit: this._config.urlEncodedLimit, extended: true }));\n\n                if (this._config.webserver_middlewares && this._config.webserver_middlewares.length) {\n                    this._config.webserver_middlewares.forEach((middleware) => {\n                        this.webserver.use(middleware);\n                    });\n                }\n\n                this.http = http.createServer(this.webserver);\n\n                this.http.listen(process.env.port || process.env.PORT || 3000, () => {\n                    if (this._config.disable_console !== true) {\n                        console.log(`Webhook endpoint online:  http://localhost:${ process.env.PORT || 3000 }${ this._config.webhook_uri }`);\n                    }\n                    this.completeDep('webserver');\n                });\n            } else {\n                this.webserver = this._config.webserver;\n            }\n        }\n\n        if (!this._config.adapter) {\n            const adapterConfig = { ...this._config.adapterConfig };\n            debug('Configuring BotFrameworkAdapter:', adapterConfig);\n            this.adapter = new BotkitBotFrameworkAdapter(adapterConfig);\n            if (this.webserver) {\n                if (this._config.disable_console !== true) {\n                    console.log('Open this bot in Bot Framework Emulator: bfemulator://livechat.open?botUrl=' + encodeURIComponent(`http://localhost:${ process.env.PORT || 3000 }${ this._config.webhook_uri }`));\n                }\n            }\n        } else {\n            debug('Using pre-configured adapter.');\n            this.adapter = this._config.adapter;\n        }\n\n        // If a webserver has been configured, auto-configure the default webhook url\n        if (this.webserver) {\n            this.configureWebhookEndpoint();\n        }\n\n        // initialize the plugins array.\n        this.plugin_list = [];\n        this._plugins = {};\n\n        // if an adapter has been configured, add it as a plugin.\n        if (this.adapter) {\n            // MAGIC: Treat the adapter as a botkit plugin\n            // which allows them to be carry their own platform-specific behaviors\n            this.usePlugin(this.adapter);\n        }\n\n        this.completeDep('booted');\n    }\n\n    /**\n     * Shutdown the webserver and prepare to terminate the app.\n     * Causes Botkit to first emit a special `shutdown` event, process any bound handlers, and then finally terminate the webserver.\n     * Bind any necessary cleanup helpers to the shutdown event - for example, close the connection to mongo.\n     *\n     * ```javascript\n     * await controller.shutdown();\n     * controller.on('shutdown', async() => {\n     *      console.log('Bot is shutting down!');\n     * });\n     * ```\n     */\n    public async shutdown(): Promise<void> {\n        // trigger a special shutdown event\n        await this.trigger('shutdown');\n\n        if (this.http) {\n            this.http.close();\n        }\n    }\n\n    /**\n     * Get a value from the configuration.\n     *\n     * For example:\n     * ```javascript\n     * // get entire config object\n     * let config = controller.getConfig();\n     *\n     * // get a specific value from the config\n     * let webhook_uri = controller.getConfig('webhook_uri');\n     * ```\n     *\n     * @param {string} key The name of a value stored in the configuration\n     * @returns {any} The value stored in the configuration (or null if absent)\n     */\n    public getConfig(key?: string): any {\n        if (key) {\n            return this._config[key];\n        } else {\n            return this._config;\n        }\n    }\n\n    /**\n     * Load a plugin module and bind all included middlewares to their respective endpoints.\n     * @param plugin_or_function A plugin module in the form of function(botkit) {...} that returns {name, middlewares, init} or an object in the same form.\n     */\n    public usePlugin(plugin_or_function: ((botkit: Botkit) => BotkitPlugin) | BotkitPlugin): void {\n        let plugin: BotkitPlugin;\n        if (typeof (plugin_or_function) === 'function') {\n            plugin = plugin_or_function(this);\n        } else {\n            plugin = plugin_or_function;\n        }\n        if (plugin.name) {\n            try {\n                this.registerPlugin(plugin.name, plugin);\n            } catch (err) {\n                console.error('ERROR IN PLUGIN REGISTER', err);\n            }\n        }\n    }\n\n    /**\n     * Called from usePlugin -- do the actual binding of middlewares for a plugin that is being loaded.\n     * @param name name of the plugin\n     * @param endpoints the plugin object that contains middleware endpoint definitions\n     */\n    private registerPlugin(name: string, endpoints: BotkitPlugin): void {\n        if (this._config.disable_console !== true) {\n            console.log('Enabling plugin: ', name);\n        }\n        if (this.plugin_list.indexOf(name) >= 0) {\n            debug('Plugin already enabled:', name);\n            return;\n        }\n        this.plugin_list.push(name);\n\n        if (endpoints.middlewares) {\n            for (const mw in endpoints.middlewares) {\n                for (let e = 0; e < endpoints.middlewares[mw].length; e++) {\n                    this.middleware[mw].use(endpoints.middlewares[mw][e]);\n                }\n            }\n        }\n\n        if (endpoints.init) {\n            try {\n                endpoints.init(this);\n            } catch (err) {\n                if (err) {\n                    throw new Error(err);\n                }\n            }\n        }\n\n        debug('Plugin Enabled: ', name);\n    }\n\n    /**\n     * (Plugins only) Extend Botkit's controller with new functionality and make it available globally via the controller object.\n     *\n     * ```javascript\n     *\n     * // define the extension interface\n     * let extension = {\n     *         stuff: () => { return 'stuff' }\n     * }\n     *\n     * // register the extension\n     * controller.addPluginExtension('foo', extension);\n     *\n     * // call extension\n     * controller.plugins.foo.stuff();\n     *\n     *\n     * ```\n     * @param name name of plugin\n     * @param extension an object containing methods\n     */\n    public addPluginExtension(name: string, extension: any): void {\n        debug('Plugin extension added: controller.' + name);\n        this._plugins[name] = extension;\n    }\n\n    /**\n     * Access plugin extension methods.\n     * After a plugin calls `controller.addPluginExtension('foo', extension_methods)`, the extension will then be available at\n     * `controller.plugins.foo`\n     */\n    public get plugins(): {[key: string]: any} {\n        return this._plugins;\n    }\n\n    /**\n     * Expose a folder to the web as a set of static files.\n     * Useful for plugins that need to bundle additional assets!\n     *\n     * ```javascript\n     * // make content of the local public folder available at http://MYBOTURL/public/myplugin\n     * controller.publicFolder('/public/myplugin', __dirname + '/public);\n     * ```\n     * @param alias the public alias ie /myfiles\n     * @param path the actual path something like `__dirname + '/public'`\n     */\n    public publicFolder(alias, path): void {\n        if (this.webserver) {\n            debug('Make folder public: ', path, 'at alias', alias);\n            this.webserver.use(alias, express.static(path));\n        } else {\n            throw new Error('Cannot create public folder alias when webserver is disabled');\n        }\n    }\n\n    /**\n     * Convert a local path from a plugin folder to a full path relative to the webserver's main views folder.\n     * Allows a plugin to bundle views/layouts and make them available to the webserver's renderer.\n     * @param path_to_view something like path.join(__dirname,'views')\n     */\n    public getLocalView(path_to_view): string {\n        if (this.webserver) {\n            return path.relative(path.join(this.webserver.get('views')), path_to_view);\n        } else {\n            throw new Error('Cannot get local view when webserver is disabled');\n        }\n    }\n\n    /**\n     * (For use by Botkit plugins only) - Add a dependency to Botkit's bootup process that must be marked as completed using `completeDep()`.\n     * Botkit's `controller.ready()` function will not fire until all dependencies have been marked complete.\n     *\n     * For example, a plugin that needs to do an asynchronous task before Botkit proceeds might do:\n     * ```javascript\n     * controller.addDep('my_async_plugin');\n     * somethingAsync().then(function() {\n     *  controller.completeDep('my_async_plugin');\n     * });\n     * ```\n     *\n     * @param name {string} The name of the dependency that is being loaded.\n     */\n    public addDep(name: string): void {\n        debug(`Waiting for ${ name }`);\n        this._deps[name] = false;\n    }\n\n    /**\n     * (For use by plugins only) - Mark a bootup dependency as loaded and ready to use\n     * Botkit's `controller.ready()` function will not fire until all dependencies have been marked complete.\n\n     * @param name {string} The name of the dependency that has completed loading.\n     */\n    public completeDep(name: string): boolean {\n        debug(`${ name } ready`);\n\n        this._deps[name] = true;\n\n        for (const key in this._deps) {\n            if (this._deps[key] === false) {\n                return false;\n            }\n        }\n\n        // everything is done!\n        this.signalBootComplete();\n        return true;\n    }\n\n    /**\n     * This function gets called when all of the bootup dependencies are completely loaded.\n     */\n    private signalBootComplete(): void {\n        this.booted = true;\n        for (let h = 0; h < this._bootCompleteHandlers.length; h++) {\n            const handler = this._bootCompleteHandlers[h];\n            handler.call(this);\n        }\n    }\n\n    /**\n     * Use `controller.ready()` to wrap any calls that require components loaded during the bootup process.\n     * This will ensure that the calls will not be made until all of the components have successfully been initialized.\n     *\n     * For example:\n     * ```javascript\n     * controller.ready(() => {\n     *\n     *   controller.loadModules(__dirname + '/features');\n     *\n     * });\n     * ```\n     *\n     * @param handler {function} A function to run when Botkit is booted and ready to run.\n     */\n    public ready(handler: () => any): void {\n        if (this.booted) {\n            handler.call(this);\n        } else {\n            this._bootCompleteHandlers.push(handler);\n        }\n    }\n\n    /*\n     * Set up a web endpoint to receive incoming messages,\n     * pass them through a normalization process, and then ingest them for processing.\n     */\n    private configureWebhookEndpoint(): void {\n        if (this.webserver) {\n            this.webserver.post(this._config.webhook_uri, (req, res) => {\n                // Allow the Botbuilder middleware to fire.\n                // this middleware is responsible for turning the incoming payload into a BotBuilder Activity\n                // which we can then use to turn into a BotkitMessage\n                this.adapter.processActivity(req, res, this.handleTurn.bind(this)).catch((err) => {\n                    // todo: expose this as a global error handler?\n                    console.error('Experienced an error inside the turn handler', err);\n                    throw err;\n                });\n            });\n        } else {\n            throw new Error('Cannot configure webhook endpoints when webserver is disabled');\n        }\n    }\n\n    /**\n     * Accepts the result of a BotBuilder adapter's `processActivity()` method and processes it into a Botkit-style message and BotWorker instance\n     * which is then used to test for triggers and emit events.\n     * NOTE: This method should only be used in custom adapters that receive messages through mechanisms other than the main webhook endpoint (such as those received via websocket, for example)\n     * @param turnContext {TurnContext} a TurnContext representing an incoming message, typically created by an adapter's `processActivity()` method.\n     */\n    public async handleTurn(turnContext: TurnContext): Promise<any> {\n        debug('INCOMING ACTIVITY:', turnContext.activity);\n\n        // Turn this turnContext into a Botkit message.\n        const message: BotkitMessage = {\n            // ...turnContext.activity,\n            ...turnContext.activity.channelData, // start with all the fields that were in the original incoming payload. NOTE: this is a shallow copy, is that a problem?\n\n            // if Botkit has further classified this message, use that sub-type rather than the Activity type\n            type: (turnContext.activity.channelData && turnContext.activity.channelData.botkitEventType) ? turnContext.activity.channelData.botkitEventType : turnContext.activity.type,\n\n            // normalize the user, text and channel info\n            user: turnContext.activity.from.id,\n            text: turnContext.activity.text,\n            channel: turnContext.activity.conversation.id,\n\n            value: turnContext.activity.value,\n\n            // generate a conversation reference, for replies.\n            // included so people can easily capture it for resuming\n            reference: TurnContext.getConversationReference(turnContext.activity),\n\n            // include the context possible useful.\n            context: turnContext,\n\n            // include the full unmodified record here\n            incoming_message: turnContext.activity\n        };\n\n        // Stash the Botkit message in\n        turnContext.turnState.set('botkitMessage', message);\n\n        // Create a dialog context\n        const dialogContext = await this.dialogSet.createContext(turnContext);\n\n        // Spawn a bot worker with the dialogContext\n        const bot = await this.spawn(dialogContext);\n\n        return new Promise<void>((resolve, reject) => {\n            this.middleware.ingest.run(bot, message, async (err, bot, message) => {\n                if (err) {\n                    reject(err);\n                } else {\n                    this.middleware.receive.run(bot, message, async (err, bot, message) => {\n                        if (err) {\n                            reject(err);\n                        } else {\n                            const interrupt_results = await this.listenForInterrupts(bot, message);\n\n                            if (interrupt_results === false) {\n                                // Continue dialog if one is present\n                                const dialog_results = await dialogContext.continueDialog();\n                                if (dialog_results && dialog_results.status === DialogTurnStatus.empty) {\n                                    await this.processTriggersAndEvents(bot, message);\n                                }\n                            }\n\n                            // make sure changes to the state get persisted after the turn is over.\n                            await this.saveState(bot);\n                            resolve();\n                        }\n                    });\n                }\n            });\n        });\n    }\n\n    /**\n     * Save the current conversation state pertaining to a given BotWorker's activities.\n     * Note: this is normally called internally and is only required when state changes happen outside of the normal processing flow.\n     * @param bot {BotWorker} a BotWorker instance created using `controller.spawn()`\n     */\n    public async saveState(bot: BotWorker): Promise<void> {\n        await this.conversationState.saveChanges(bot.getConfig('context'));\n    }\n\n    /**\n     * Ingests a message and evaluates it for triggers, run the receive middleware, and triggers any events.\n     * Note: This is normally called automatically from inside `handleTurn()` and in most cases should not be called directly.\n     * @param bot {BotWorker} An instance of the bot\n     * @param message {BotkitMessage} an incoming message\n     */\n    private async processTriggersAndEvents(bot: BotWorker, message: BotkitMessage): Promise<any> {\n        return new Promise((resolve, reject) => {\n            this.middleware.interpret.run(bot, message, async (err, bot, message) => {\n                if (err) {\n                    return reject(err);\n                }\n                const listen_results = await this.listenForTriggers(bot, message);\n\n                if (listen_results !== false) {\n                    resolve(listen_results);\n                } else {\n                    // Trigger event handlers\n                    const trigger_results = await this.trigger(message.type, bot, message);\n\n                    resolve(trigger_results);\n                }\n            });\n        });\n    }\n\n    /**\n     * Evaluates an incoming message for triggers created with `controller.hears()` and fires any relevant handler functions.\n     * @param bot {BotWorker} An instance of the bot\n     * @param message {BotkitMessage} an incoming message\n     */\n    private async listenForTriggers(bot: BotWorker, message: BotkitMessage): Promise<any> {\n        if (this._triggers[message.type]) {\n            const triggers = this._triggers[message.type];\n            for (let t = 0; t < triggers.length; t++) {\n                const test_results = await this.testTrigger(triggers[t], message);\n                if (test_results) {\n                    debug('Heard pattern: ', triggers[t].pattern);\n                    const trigger_results = await triggers[t].handler.call(this, bot, message);\n                    return trigger_results;\n                }\n            }\n\n            // nothing has triggered...return false\n            return false;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * Evaluates an incoming message for triggers created with `controller.interrupts()` and fires any relevant handler functions.\n     * @param bot {BotWorker} An instance of the bot\n     * @param message {BotkitMessage} an incoming message\n     */\n    private async listenForInterrupts(bot: BotWorker, message: BotkitMessage): Promise<any> {\n        if (this._interrupts[message.type]) {\n            const triggers = this._interrupts[message.type];\n            for (let t = 0; t < triggers.length; t++) {\n                const test_results = await this.testTrigger(triggers[t], message);\n                if (test_results) {\n                    debug('Heard interruption: ', triggers[t].pattern);\n                    const trigger_results = await triggers[t].handler.call(this, bot, message);\n                    return trigger_results;\n                }\n            }\n\n            // nothing has triggered...return false\n            return false;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * Evaluates a single trigger and return true if the incoming message matches the conditions\n     * @param trigger {BotkitTrigger} a trigger definition\n     * @param message {BotkitMessage} an incoming message\n     */\n    private async testTrigger(trigger: BotkitTrigger, message: BotkitMessage): Promise<boolean> {\n        if (trigger.type === 'string') {\n            const test = new RegExp(trigger.pattern as string, 'i');\n            if (message.text && message.text.match(test)) {\n                return true;\n            }\n        } else if (trigger.type === 'regexp') {\n            const test = trigger.pattern as RegExp;\n            if (message.text && message.text.match(test)) {\n                message.matches = message.text.match(test);\n                return true;\n            }\n        } else if (trigger.type === 'function') {\n            const test = trigger.pattern as (message) => Promise<boolean>;\n            return await test(message);\n        }\n\n        return false;\n    }\n\n    /**\n     * Instruct your bot to listen for a pattern, and do something when that pattern is heard.\n     * Patterns will be \"heard\" only if the message is not already handled by an in-progress dialog.\n     * To \"hear\" patterns _before_ dialogs are processed, use `controller.interrupts()` instead.\n     *\n     * For example:\n     * ```javascript\n     * // listen for a simple keyword\n     * controller.hears('hello','message', async(bot, message) => {\n     *  await bot.reply(message,'I heard you say hello.');\n     * });\n     *\n     * // listen for a regular expression\n     * controller.hears(new RegExp(/^[A-Z\\s]+$/), 'message', async(bot, message) => {\n     *  await bot.reply(message,'I heard a message IN ALL CAPS.');\n     * });\n     *\n     * // listen using a function\n     * controller.hears(async (message) => { return (message.intent === 'hello') }, 'message', async(bot, message) => {\n     *  await bot.reply(message,'This message matches the hello intent.');\n     * });\n     * ```\n     * @param patterns {} One or more string, regular expression, or test function\n     * @param events {} A list of event types that should be evaluated for the given patterns\n     * @param handler {BotkitHandler}  a function that will be called should the pattern be matched\n     */\n    public hears(patterns: (string | RegExp | { (message: BotkitMessage): Promise<boolean> })[] | RegExp | string | { (message: BotkitMessage): Promise<boolean> }, events: string | string[], handler: BotkitHandler): void {\n        if (!Array.isArray(patterns)) {\n            patterns = [patterns];\n        }\n\n        if (typeof events === 'string') {\n            events = events.split(/,/).map(e => e.trim());\n        }\n\n        debug('Registering hears for ', events);\n\n        for (let p = 0; p < patterns.length; p++) {\n            for (let e = 0; e < events.length; e++) {\n                const event = events[e];\n                const pattern = patterns[p];\n\n                if (!this._triggers[event]) {\n                    this._triggers[event] = [];\n                }\n\n                const trigger = {\n                    pattern: pattern,\n                    handler: handler,\n                    type: null\n                };\n\n                if (typeof pattern === 'string') {\n                    trigger.type = 'string';\n                } else if (pattern instanceof RegExp) {\n                    trigger.type = 'regexp';\n                } else if (typeof pattern === 'function') {\n                    trigger.type = 'function';\n                }\n\n                this._triggers[event].push(trigger);\n            }\n        }\n    }\n\n    /**\n     * Instruct your bot to listen for a pattern, and do something when that pattern is heard.\n     * Interruptions work just like \"hears\" triggers, but fire _before_ the dialog system is engaged,\n     * and thus handlers will interrupt the normal flow of messages through the processing pipeline.\n     *\n     * ```javascript\n     * controller.interrupts('help','message', async(bot, message) => {\n     *\n     *  await bot.reply(message,'Before anything else, you need some help!')\n     *\n     * });\n     * ```\n     * @param patterns {} One or more string, regular expression, or test function\n     * @param events {} A list of event types that should be evaluated for the given patterns\n     * @param handler {BotkitHandler}  a function that will be called should the pattern be matched\n     */\n    public interrupts(patterns: (string | RegExp | { (message: BotkitMessage): Promise<boolean> })[] | RegExp | RegExp[] | string | { (message: BotkitMessage): Promise<boolean> }, events: string | string[], handler: BotkitHandler): void {\n        if (!Array.isArray(patterns)) {\n            patterns = [patterns];\n        }\n\n        if (typeof events === 'string') {\n            events = events.split(/,/).map(e => e.trim());\n        }\n        debug('Registering hears for ', events);\n\n        for (let p = 0; p < patterns.length; p++) {\n            for (let e = 0; e < events.length; e++) {\n                const event = events[e];\n                const pattern = patterns[p];\n\n                if (!this._interrupts[event]) {\n                    this._interrupts[event] = [];\n                }\n\n                const trigger = {\n                    pattern: pattern,\n                    handler: handler,\n                    type: null\n                };\n\n                if (typeof pattern === 'string') {\n                    trigger.type = 'string';\n                } else if (pattern instanceof RegExp) {\n                    trigger.type = 'regexp';\n                } else if (typeof pattern === 'function') {\n                    trigger.type = 'function';\n                }\n\n                this._interrupts[event].push(trigger);\n            }\n        }\n    }\n\n    /**\n     * Bind a handler function to one or more events.\n     *\n     * ```javascript\n     * controller.on('conversationUpdate', async(bot, message) => {\n     *\n     *  await bot.reply(message,'I received a conversationUpdate event.');\n     *\n     * });\n     * ```\n     *\n     * @param events {} One or more event names\n     * @param handler {BotkitHandler} a handler function that will fire whenever one of the named events is received.\n     */\n    public on(events: string | string[], handler: BotkitHandler): void {\n        if (typeof events === 'string') {\n            events = events.split(/,/).map(e => e.trim());\n        }\n\n        debug('Registering handler for: ', events);\n        events.forEach((event) => {\n            if (!this._events[event]) {\n                this._events[event] = [];\n            }\n            this._events[event].push(handler);\n        });\n    }\n\n    /**\n     * Trigger an event to be fired.  This will cause any bound handlers to be executed.\n     * Note: This is normally used internally, but can be used to emit custom events.\n     *\n     * ```javascript\n     * // fire a custom event\n     * controller.trigger('my_custom_event', bot, message);\n     *\n     * // handle the custom event\n     * controller.on('my_custom_event', async(bot, message) => {\n     *  //... do something\n     * });\n     * ```\n     *\n     * @param event {string} the name of the event\n     * @param bot {BotWorker} a BotWorker instance created using `controller.spawn()`\n     * @param message {BotkitMessagE} An incoming message or event\n     */\n    public async trigger(event: string, bot?: BotWorker, message?: BotkitMessage): Promise<any> {\n        debug('Trigger event: ', event);\n        if (this._events[event] && this._events[event].length) {\n            for (let h = 0; h < this._events[event].length; h++) {\n                try {\n                    const handler_results = await this._events[event][h].call(bot, bot, message);\n                    if (handler_results === false) {\n                        break;\n                    }\n                } catch (err) {\n                    console.error('Error in trigger handler', err);\n                    throw Error(err);\n                }\n            }\n        }\n    }\n\n    /**\n     * Create a platform-specific BotWorker instance that can be used to respond to messages or generate new outbound messages.\n     * The spawned `bot` contains all information required to process outbound messages and handle dialog state, and may also contain extensions\n     * for handling platform-specific events or activities.\n     * @param config {any} Preferably receives a DialogContext, though can also receive a TurnContext. If excluded, must call `bot.changeContext(reference)` before calling any other method.\n     * @param adapter {BotAdapter} An optional reference to a specific adapter from which the bot will be spawned. If not specified, will use the adapter from which the configuration object originates. Required for spawning proactive bots in a multi-adapter scenario.\n     */\n    public async spawn(config?: any, custom_adapter?: BotAdapter): Promise<BotWorker> {\n        if (config instanceof TurnContext) {\n            config = {\n                dialogContext: await this.dialogSet.createContext(config as TurnContext),\n                context: config as TurnContext,\n                reference: TurnContext.getConversationReference(config.activity),\n                activity: config.activity\n            };\n        } else if (config instanceof DialogContext) {\n            config = {\n                dialogContext: config,\n                reference: TurnContext.getConversationReference(config.context.activity),\n                context: config.context,\n                activity: config.context.activity\n            };\n        }\n\n        let worker: BotWorker = null;\n        const adapter = custom_adapter || ((config && config.context && config.context.adapter) ? config.context.adapter : this.adapter);\n\n        if (adapter.botkit_worker) {\n            const CustomBotWorker = adapter.botkit_worker;\n            worker = new CustomBotWorker(this, config);\n        } else {\n            worker = new BotWorker(this, config);\n        }\n\n        // make sure the adapter is available in a standard location.\n        worker.getConfig().adapter = adapter;\n\n        return new Promise((resolve, reject) => {\n            this.middleware.spawn.run(worker, (err, worker) => {\n                if (err) {\n                    reject(err);\n                } else {\n                    resolve(worker);\n                }\n            });\n        });\n    }\n\n    /**\n     * Load a Botkit feature module\n     *\n     * @param p {string} path to module file\n     */\n    public loadModule(p: string): void {\n        debug('Load Module:', p);\n        // eslint-disable-next-line @typescript-eslint/no-var-requires\n        const module = require(p);\n        // Handle both CJS `module.exports` and ESM `export default` syntax.\n        if (typeof module === 'function') {\n            module(this);\n        } else if (module && typeof module.default === 'function') {\n            module.default(this);\n        } else {\n            throw new Error(`Failed to load '${ p }', did you export a function?`);\n        }\n    }\n\n    /**\n     * Load all Botkit feature modules located in a given folder.\n     *\n     * ```javascript\n     * controller.ready(() => {\n     *\n     *  // load all modules from sub-folder features/\n     *  controller.loadModules('./features');\n     *\n     * });\n     * ```\n     *\n     * @param p {string} path to a folder of module files\n     * @param exts {string[]} the extensions that you would like to load (default: ['.js'])\n     */\n    public loadModules(p: string, exts: string[] = ['.js']): void {\n        // load all the .js|.ts files from this path\n        fs.readdirSync(p).filter((f) => {\n            return exts.includes(path.extname(f));\n        }).forEach((file) => {\n            this.loadModule(path.join(p, file));\n        });\n    }\n\n    /**\n     * Add a dialog to the bot, making it accessible via `bot.beginDialog(dialog_id)`\n     *\n     * ```javascript\n     * // Create a dialog -- `BotkitConversation` is just one way to create a dialog\n     * const my_dialog = new BotkitConversation('my_dialog', controller);\n     * my_dialog.say('Hello');\n     *\n     * // Add the dialog to the Botkit controller\n     * controller.addDialog(my_dialog);\n     *\n     * // Later on, trigger the dialog into action!\n     * controller.on('message', async(bot, message) => {\n     *      await bot.beginDialog('my_dialog');\n     * });\n     * ```\n     *\n     * @param dialog A dialog to be added to the bot's dialog set\n     */\n    public addDialog(dialog: Dialog): void {\n        // add the actual dialog\n        this.dialogSet.add(dialog);\n\n        // add a wrapper dialog that will be called by bot.beginDialog\n        // and is responsible for capturing the parent results\n        this.dialogSet.add(new WaterfallDialog(dialog.id + ':botkit-wrapper', [\n            async (step): Promise<any> => {\n                return step.beginDialog(dialog.id, step.options);\n            },\n            async (step): Promise<any> => {\n                const bot = await this.spawn(step.context);\n\n                await this.trigger(dialog.id + ':after', bot, step.result);\n                return step.endDialog(step.result);\n            }\n        ]));\n    }\n\n    /**\n     * Bind a handler to the end of a dialog.\n     * NOTE: bot worker cannot use bot.reply(), must use bot.send()\n     *\n     * [Learn more about handling end-of-conversation](../docs/conversations.md#handling-end-of-conversation)\n     * @param dialog the dialog object or the id of the dialog\n     * @param handler a handler function in the form `async(bot, dialog_results) => {}`\n     */\n    public afterDialog(dialog: Dialog | string, handler: BotkitHandler): void {\n        let id = '';\n        if (typeof (dialog) === 'string') {\n            id = dialog as string;\n        } else {\n            id = dialog.id;\n        }\n\n        this.on(id + ':after', handler);\n    }\n}\n"
  },
  {
    "path": "packages/botkit/src/dialogWrapper.ts",
    "content": "/**\n * @module botkit\n */\n/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { DialogContext } from 'botbuilder-dialogs';\nimport { BotkitConversationStep } from './conversation';\n\n/**\n * This class is used to provide easy access to common actions taken on active BotkitConversation instances.\n * These objects are passed into handlers bound to BotkitConversations using .before .onChange and conditional handler functions passed to .ask and .addQuestion\n * Grants access to convo.vars convo.gotoThread() convo.setVar() and convo.repeat().\n */\nexport class BotkitDialogWrapper {\n    private dc: DialogContext;\n    private step: BotkitConversationStep;\n    /**\n     * An object containing variables and user responses from this conversation.\n     */\n    public vars: {\n        [key: string]: any;\n    }\n\n    public constructor(dc: DialogContext, step: BotkitConversationStep) {\n        this.dc = dc;\n        this.step = step;\n        this.vars = this.step.values;\n    }\n\n    /**\n     * Jump immediately to the first message in a different thread.\n     * @param thread Name of a thread\n     */\n    public async gotoThread(thread: string): Promise<void> {\n        this.step.index = 0;\n        this.step.thread = thread;\n    }\n\n    /**\n     * Repeat the last message sent on the next turn.\n     */\n    public async repeat(): Promise<void> {\n        // move back one step next turn the bot will repeat with the last message sent.\n        this.step.index--;\n    }\n\n    /**\n     * Stop the dialog.\n     */\n    public async stop(): Promise<void> {\n        // set this to 1 bigger than the total length of the thread.\n        this.step.index = this.step.threadLength + 1;\n    }\n\n    /**\n     * Set the value of a variable that will be available to messages in the conversation.\n     * Equivalent to convo.vars.key = val;\n     * Results in {{vars.key}} being replaced with the value in val.\n     * @param key the name of the variable\n     * @param val the value for the variable\n     */\n    public setVar(key, val): void {\n        this.vars[key] = val;\n    }\n}\n"
  },
  {
    "path": "packages/botkit/src/index.ts",
    "content": "/**\n * @module botkit\n */\n/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport * from './core';\nexport * from './conversation';\nexport * from './botworker';\nexport * from './dialogWrapper';\nexport * from './teamsHelpers';\nexport * from './testClient';\n"
  },
  {
    "path": "packages/botkit/src/teamsHelpers.ts",
    "content": "/**\n * @module botkit\n */\n/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\nimport { BotkitMessage } from './core';\nimport { BotWorker } from './botworker';\nimport { TeamsInfo, MiddlewareSet, TurnContext } from 'botbuilder';\n\n/**\n * This is a specialized version of [Botkit's core BotWorker class](core.md#BotWorker) that includes additional methods for interacting with Microsoft Teams.\n * It includes all functionality from the base class, as well as the extension methods below.\n * This BotWorker is used with the built-in Bot Framework adapter.\n * @noInheritDoc\n */\nexport class TeamsBotWorker extends BotWorker {\n  /**\n   * Grants access to the TeamsInfo helper class\n   * See: https://docs.microsoft.com/en-us/javascript/api/botbuilder/teamsinfo?view=botbuilder-ts-latest\n   */\n  public teams: TeamsInfo = TeamsInfo;\n\n  /**\n   * Reply to a Teams task module task/fetch or task/submit with a task module response.\n   * See https://docs.microsoft.com/en-us/microsoftteams/platform/task-modules-and-cards/task-modules/task-modules-bots\n   * @param message\n   * @param taskInfo an object in the form {type, value}\n   */\n  public async replyWithTaskInfo(message: BotkitMessage, taskInfo: any): Promise<any> {\n      if (!taskInfo || taskInfo === {}) {\n      // send a null response back\n          taskInfo = {\n              type: 'message',\n              value: ''\n          };\n      }\n      return new Promise((resolve, reject) => {\n          this.controller.middleware.send.run(this, taskInfo, async (err, bot, taskInfo) => {\n              if (err) {\n                  return reject(err);\n              }\n              resolve(await this.getConfig('context').sendActivity({\n                  type: 'invokeResponse',\n                  value: {\n                      status: 200,\n                      body: {\n                          task: taskInfo\n                      }\n                  }\n              }));\n          });\n      });\n  }\n}\n\n/**\n * When used, causes Botkit to emit special events for teams \"invokes\"\n * Based on https://github.com/microsoft/botbuilder-js/blob/master/libraries/botbuilder/src/teamsActivityHandler.ts\n * This allows Botkit bots to respond directly to task/fetch or task/submit events, as an example.\n * To use this, bind it to the adapter before creating the Botkit controller:\n * ```javascript\n * const Botkit = new Botkit({...});\n * botkit.adapter.use(new TeamsInvokeMiddleware());\n *\n * // can bind directly to task/fetch, task/submit and other invoke types used by teams\n * controller.on('task/fetch', async(bot, message) => {\n *    await bot.replyWithTaskInfo(message, taskInfo);\n * });\n * ```\n */\nexport class TeamsInvokeMiddleware extends MiddlewareSet {\n    /**\n     * Not for direct use - implements the MiddlewareSet's required onTurn function used to process the event\n     * @param context\n     * @param next\n     */\n    public async onTurn(context: TurnContext, next: () => Promise<any>): Promise<void> {\n        if (context.activity.type === 'invoke') {\n            if (!context.activity.name && context.activity.channelId === 'msteams') {\n                context.activity.channelData.botkitEventType = 'cardAction';\n            } else {\n                switch (context.activity.name) {\n                case 'fileConsent/invoke':\n                case 'actionableMessage/executeAction':\n                case 'composeExtension/queryLink':\n                case 'composeExtension/query':\n                case 'composeExtension/selectItem':\n                case 'composeExtension/submitAction':\n                case 'composeExtension/fetchTask':\n                case 'composeExtension/querySettingUrl':\n                case 'composeExtension/setting':\n                case 'composeExtension/onCardButtonClicked':\n                case 'task/fetch':\n                case 'task/submit':\n                    context.activity.channelData.botkitEventType = context.activity.name;\n                    break;\n                }\n            }\n        }\n        await next();\n    }\n}\n"
  },
  {
    "path": "packages/botkit/src/testClient.ts",
    "content": "/**\n * @module botkit\n */\n/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\nimport {\n    Activity,\n    AutoSaveStateMiddleware,\n    ConversationState,\n    MemoryStorage,\n    Middleware,\n    TestAdapter,\n    TurnContext\n} from 'botbuilder-core';\nimport { Dialog, DialogSet, DialogTurnResult, DialogTurnStatus } from 'botbuilder-dialogs';\nimport { Botkit } from './core';\n\n/**\n * A client for testing dialogs in isolation.\n */\nexport class BotkitTestClient {\n    private readonly _callback: (turnContext: TurnContext) => Promise<void>;\n    private readonly _testAdapter: TestAdapter;\n    public dialogTurnResult: DialogTurnResult;\n    public conversationState: ConversationState;\n\n    /**\n     * Create a BotkitTestClient to test a dialog without having to create a full-fledged adapter.\n     *\n     * ```javascript\n     * let client = new BotkitTestClient('test', bot, MY_DIALOG, MY_OPTIONS);\n     * let reply = await client.sendActivity('first message');\n     * assert.strictEqual(reply.text, 'first reply', 'reply failed');\n     * ```\n     *\n     * @param channelId The channelId to be used for the test.\n     * Use 'emulator' or 'test' if you are uncertain of the channel you are targeting.\n     * Otherwise, it is recommended that you use the id for the channel(s) your bot will be using and write a test case for each channel.\n     * @param bot (Required) The Botkit bot that has the skill to test.\n     * @param dialogToTest (Required) The identifier of the skill to test in the bot.\n     * @param initialDialogOptions (Optional) additional argument(s) to pass to the dialog being started.\n     * @param middlewares (Optional) a stack of middleware to be run when testing\n     * @param conversationState (Optional) A ConversationState instance to use in the test client\n     */\n    public constructor(channelId: string, bot: Botkit, dialogToTest: string | string[], initialDialogOptions?: any, middlewares?: Middleware[], conversationState?: ConversationState)\n    public constructor(testAdapter: TestAdapter, bot: Botkit, dialogToTest: string | string[], initialDialogOptions?: any, middlewares?: Middleware[], conversationState?: ConversationState)\n    public constructor(channelOrAdapter: string | TestAdapter, bot: Botkit, dialogToTest: string | string[], initialDialogOptions?: any, middlewares?: Middleware[], conversationState?: ConversationState) {\n        this.conversationState = conversationState || new ConversationState(new MemoryStorage());\n\n        const dialogState = this.conversationState.createProperty('DialogState');\n\n        let targetDialogs = [];\n        if (Array.isArray(dialogToTest)) {\n            dialogToTest.forEach((dialogName) => {\n                targetDialogs.push(\n                    bot.dialogSet.find(dialogName)\n                );\n                targetDialogs.push(\n                    bot.dialogSet.find(dialogName + '_default_prompt')\n                );\n                targetDialogs.push(\n                    bot.dialogSet.find(dialogName + ':botkit-wrapper')\n                );\n            });\n            dialogToTest = dialogToTest[0];\n        } else {\n            targetDialogs = [\n                bot.dialogSet.find(dialogToTest),\n                bot.dialogSet.find(dialogToTest + '_default_prompt'),\n                bot.dialogSet.find(dialogToTest + ':botkit-wrapper')\n            ];\n        }\n\n        this._callback = this.getDefaultCallback(targetDialogs, initialDialogOptions || null, dialogState);\n\n        if (typeof channelOrAdapter === 'string') {\n            this._testAdapter = new TestAdapter(this._callback, { channelId: channelOrAdapter }).use(new AutoSaveStateMiddleware(this.conversationState));\n        } else {\n            this._testAdapter = channelOrAdapter;\n        }\n\n        this.addUserMiddlewares(middlewares);\n    }\n\n    /**\n     * Send an activity into the dialog.\n     * @returns a TestFlow that can be used to assert replies etc\n     * @param activity an activity potentially with text\n     *\n     * ```javascript\n     * DialogTest.send('hello').assertReply('hello yourself').then(done);\n     * ```\n     */\n    public async sendActivity(activity: Partial<Activity> | string): Promise<any> {\n        if (!activity) { activity = { type: 'event' }}\n        await this._testAdapter.receiveActivity(activity);\n        return this._testAdapter.activityBuffer.shift();\n    }\n\n    /**\n     * Get the next reply waiting to be delivered (if one exists)\n     */\n    public getNextReply(): Partial<Activity> {\n        return this._testAdapter.activityBuffer.shift();\n    }\n\n    private getDefaultCallback(targetDialogs: Dialog[], initialDialogOptions: any, dialogState: any): (turnContext: TurnContext) => Promise<void> {\n        return async (turnContext: TurnContext): Promise<void> => {\n            const dialogSet = new DialogSet(dialogState);\n            targetDialogs.forEach(targetDialog => dialogSet.add(targetDialog));\n            const dialogContext = await dialogSet.createContext(turnContext);\n            this.dialogTurnResult = await dialogContext.continueDialog();\n            if (this.dialogTurnResult.status === DialogTurnStatus.empty) {\n                this.dialogTurnResult = await dialogContext.beginDialog(targetDialogs[0].id, initialDialogOptions);\n            }\n        };\n    }\n\n    private addUserMiddlewares(middlewares: Middleware[]): void {\n        if (middlewares != null) {\n            middlewares.forEach((middleware) => {\n                this._testAdapter.use(middleware);\n            });\n        }\n    }\n}\n"
  },
  {
    "path": "packages/botkit/tests/Core.tests.js",
    "content": "const assert = require('assert');\nconst { Botkit, TeamsBotWorker } = require('../');\nconst { TwilioAdapter, TwilioBotWorker } = require('../../botbuilder-adapter-twilio-sms');\n\ndescribe('Botkit', function() {\n    it('should create a Botkit controller', function() {\n        assert((new Botkit({ disable_console: true, disable_webserver: true }) instanceof Botkit), 'Botkit is wrong type');\n    });\n    it ('should spawn appropriate bot worker with a single adapter', async function() {\n        const controller = new Botkit({\n            disable_webserver: true,\n            adapter: new TwilioAdapter({enable_incomplete: true}),\n        });\n        \n        const bot = await controller.spawn({});\n        assert((bot instanceof TwilioBotWorker), 'Bot worker is wrong type');\n\n\n    });\n    it ('should spawn appropriate bot worker with a multiple adapter', async function() {\n\n        const controller = new Botkit({\n            disable_webserver: true,\n        });\n\n        const anotherAdapter = new TwilioAdapter({enable_incomplete: true});\n        \n        const bot = await controller.spawn({});\n        assert((bot instanceof TeamsBotWorker), 'Default Bot worker is wrong type');\n\n        const tbot = await controller.spawn({}, anotherAdapter);\n        assert((tbot instanceof TwilioBotWorker), 'Secondary Bot worker is wrong type');\n\n    });\n\n});\n"
  },
  {
    "path": "packages/botkit/tests/CustomAdapter.tests.js",
    "content": "const { Botkit, BotkitConversation, BotkitTestClient, BotWorker } = require('..');\nconst { TestAdapter, AutoSaveStateMiddleware } = require('botbuilder');\nconst assert = require('assert');\n\nclass FakeBotWorker extends BotWorker {\n    constructor(controller, config) {\n        super(controller, config);\n    }\n\n    getUser() {\n        return {\n            id: 123,\n            name: 'Roger'\n        };\n    };\n}\n\nclass FakeAdapter extends TestAdapter {\n  // Enables overriding the type of the BotWorker\n  // (this uses a Botkit features that allows setting a worker type)\n  botkit_worker = FakeBotWorker;\n}\n\nclass CustomTestClient extends BotkitTestClient {\n  constructor(channelId, bot, dialogToTest) {\n    super(channelId, bot, dialogToTest);\n    this._testAdapter = new FakeAdapter(this._callback, { channelId: channelId }).use(new AutoSaveStateMiddleware(this.conversationState));\n  }\n}\n\nfunction createDialog(controller) {\n    const dialog = new BotkitConversation('try_custom_worker', controller);\n\n    dialog.ask('How you like me now?', async (response, convo, bot) => {\n        const botUser = bot.getUser();\n        return bot.say(`You are: ${ botUser.name }`);\n    }, 'question');\n\n    return dialog;\n}\n\ndescribe('Test something with custom worker', () => {\n    let botkit;\n    let client;\n    let testAdapter;\n\n    it('bot can access user identity through custom bot worker', async () => {\n        testAdapter = new FakeAdapter({});\n        botkit = new Botkit({\n            disable_webserver: true,\n            disable_console: true,\n            adapter: testAdapter\n        });\n        botkit.addDialog(createDialog(botkit));\n        client = new CustomTestClient('test', botkit, ['try_custom_worker']);\n\n        // Test the dialog through the client\n        let message = await client.sendActivity('');\n        assert(message.text === 'How you like me now?');\n        message = await client.sendActivity('nice!');\n        assert(message.text === 'You are: Roger','Custom adapter spawning invalid bot');\n    });\n\n    afterEach(async () => {\n        await botkit.shutdown();\n    });\n});\n"
  },
  {
    "path": "packages/botkit/tests/Dialog.tests.js",
    "content": "const assert = require('assert');\nconst { ActivityTypes } = require('botbuilder');\nconst { Botkit, BotkitTestClient, BotkitConversation } = require('../');\n\nlet bot;\n\ndescribe('Botkit dialog', function() {\n    beforeEach(async () => {\n        bot = new Botkit({\n            disable_webserver: true,\n            disable_console: true\n        });\n    });\n\n    it('should follow a dialog', async function() {\n        const introDialog = new BotkitConversation('introduction', bot);\n        introDialog.ask({\n            type: 'message',\n            text: 'You can say Ok',\n            quick_replies: [{\n                title: 'Ok',\n                payload: 'Ok'\n            }]\n        }, [], 'continue');\n        introDialog.say('you said {{vars.continue}}');\n        introDialog.ask({\n            type: 'message',\n            text: 'say repeat'\n        }, [{\n            pattern: 'repeat',\n            handler: async (val, convo, bot, message) => {\n                await convo.repeat();\n            }\n        }, {\n            default: true,\n            handler: async () => {\n                // noop\n            }\n        }], 'choice');\n        introDialog.say('you said {{vars.choice}}');\n        bot.addDialog(introDialog);\n\n        // set up a test client\n        const client = new BotkitTestClient('test', bot, 'introduction');\n\n        // Get details for the reply\n        const quickreply_reply = await client.sendActivity();\n        assert(quickreply_reply.text === 'You can say Ok', 'wrong first message');\n        assert(quickreply_reply.channelData.quick_replies[0].title === 'Ok', 'wrong quick reply');\n\n        const next_reply = await client.sendActivity('Ok');\n        assert(next_reply.text === 'you said Ok', 'wrong reply');\n\n        const reply3 = await client.getNextReply();\n        assert(reply3.text === 'say repeat', 'wrong reply 3');\n\n        const reply4 = await client.sendActivity('repeat');\n        assert(reply4.text === 'say repeat', 'wrong reply 4');\n\n        const reply5 = await client.sendActivity('repeat');\n        assert(reply5.text === 'say repeat', 'wrong reply 5');\n\n        const reply6 = await client.sendActivity('2');\n        assert(reply6.text === 'you said 2', 'wrong reply 6');\n    });\n\n    it('should work with convo.repeat', async function() {\n        const botConvo = new BotkitConversation('testConvo', bot);\n\n        botConvo.ask({\n            text: ['what is your name?']\n        }, [\n            {\n                default: true,\n                handler: async (answer, convo, bot) => {\n                    await bot.say(`hi ${ answer }`);\n                }\n            }\n        ], 'name');\n\n        // botConvo.say('ok');\n\n        botConvo.ask({\n            text: ['what is your last name{{vars.count}}']\n        }\n        , [\n            {\n                pattern: 'smith',\n                handler: async (answer, convo, bot) => {\n                    await bot.say('I like the name smith');\n                }\n            },\n            {\n                default: true,\n                handler: async (answer, convo, bot) => {\n                    await bot.say('name not recognized, say another name');\n\n                    let count = convo.vars.count;\n                    if (!count) {\n                        count = 1;\n                    } else {\n                        count++;\n                    }\n                    convo.setVar('count', count)/\n                    await convo.repeat();\n                }\n            }\n        ], 'last-name');\n\n        bot.addDialog(botConvo);\n\n        // set up a test client\n        const client = new BotkitTestClient('test', bot, 'testConvo');\n\n        // Get details for the reply\n        const quickreply_reply = await client.sendActivity();\n        assert(quickreply_reply.text === 'what is your name?', 'did not get name prompt');\n\n        const next_reply = await client.sendActivity('chester');\n        assert(next_reply.text === 'hi chester', 'did not echo name');\n\n        // const ok = await client.getNextReply();\n        // assert(ok.text === 'ok','did not hear ok');\n\n        const reply3 = await client.getNextReply();\n        assert(reply3.text === 'what is your last name', 'did not get last name prompt');\n\n        const reply4 = await client.sendActivity('phillips');\n        assert(reply4.text === 'name not recognized, say another name', 'did not get invalid error 1');\n\n        const reply5 = await client.getNextReply();\n        assert(reply5.text === 'what is your last name1', 'did not get reprompt');\n\n        const reply6 = await client.sendActivity('brown');\n        assert(reply6.text === 'name not recognized, say another name', 'did not get invalid error 2');\n\n        const reply8 = await client.getNextReply();\n        assert(reply8.text === 'what is your last name2', 'did not get reprompt');\n\n        const reply9 = await client.sendActivity('smith');\n        assert(reply9.text === 'I like the name smith', 'did not get final confirm');\n    });\n\n\n    it('should work with convo.repeat in an onchange', async function() {\n        const botConvo = new BotkitConversation('testConvo', bot);\n\n        botConvo.ask({\n            text: ['what is your name?']\n        }, [], 'name');\n\n        botConvo.onChange('name', async(response,convo)=>{ \n            if (response != 'smith') {\n                await convo.repeat();\n            }\n        });\n\n        botConvo.say('done');\n\n        bot.addDialog(botConvo);\n\n        // set up a test client\n        const client = new BotkitTestClient('test', bot, 'testConvo');\n        let msg = await client.sendActivity('');\n        assert(msg.text == 'what is your name?', 'initial prompt wrong');\n        msg = await client.sendActivity('phillips');\n        assert(msg.text == 'what is your name?', 'reprompt wrong');\n        msg = await client.sendActivity('brown');\n        assert(msg.text == 'what is your name?', 'reprompt 2 wrong');\n        msg = await client.sendActivity('smith');\n        assert(msg.text == 'done', 'did not wrap up');\n\n    });\n\n    it('should work with call to addchildDialog', async function() {\n        const botConvo = new BotkitConversation('testConvo', bot);\n        botConvo.ask('What is your name?', async (response, convo, bot) => {\n        }, 'name');\n        botConvo.addChildDialog('testConvo2', 'stuff');\n        botConvo.say('got it.');\n        bot.addDialog(botConvo);\n\n        const botConvo2 = new BotkitConversation('testConvo2', bot);\n\n        botConvo2.ask('What is your favorite color?', async (response, convo, bot) => {\n            // noop\n        }, 'color');\n        botConvo2.say('ok');\n        bot.addDialog(botConvo2);\n\n        // set up a test client\n        const client = new BotkitTestClient('test', bot, ['testConvo', 'testConvo2']);\n\n        const prompt = await client.sendActivity('..');\n        assert(prompt.text === 'What is your name?', 'wrong prompt 1');\n\n        const prompt2 = await client.sendActivity('ben');\n        assert(prompt2.text === 'What is your favorite color?', 'wrong prompt 2');\n\n        const reply = await client.sendActivity('black');\n        assert(reply.text == 'ok', 'wrong reply');\n\n        const reply2 = await client.getNextReply();\n        assert(reply2.text == 'got it.', 'wrong reply 2 in addChildDialog test');\n    });\n\n    it('should work with call to addGotoDialog', async function() {\n        const botConvo = new BotkitConversation('testConvo', bot);\n        botConvo.ask('What is your name?', async (response, convo, bot) => {\n        }, 'name');\n        botConvo.addGotoDialog('testConvo2');\n        botConvo.say('got it.');\n        bot.addDialog(botConvo);\n\n        const botConvo2 = new BotkitConversation('testConvo2', bot);\n        botConvo2.ask('What is your favorite color?', async (response, convo, bot) => {\n            // noop\n        }, 'color');\n        botConvo2.say('ok');\n        bot.addDialog(botConvo2);\n\n        // set up a test client\n        const client = new BotkitTestClient('test', bot, ['testConvo', 'testConvo2']);\n\n        const prompt = await client.sendActivity('..');\n        assert(prompt.text === 'What is your name?', 'wrong prompt 1');\n\n        const prompt2 = await client.sendActivity('ben');\n        assert(prompt2.text === 'What is your favorite color?', 'wrong prompt 2');\n\n        const reply = await client.sendActivity('black');\n        assert(reply.text == 'ok', 'wrong reply');\n\n        const reply2 = await client.getNextReply();\n        assert(reply2 == null, 'wrong reply 2 in addGotoDialog test');\n    });\n\n    it('should work with call to beginDialog in handler', async function() {\n        const botConvo = new BotkitConversation('testConvo', bot);\n        botConvo.ask('What is your name?', async (response, convo, bot) => {\n            await bot.beginDialog('testConvo2');\n        }, 'name');\n        botConvo.say('got it.');\n        bot.addDialog(botConvo);\n\n        const botConvo2 = new BotkitConversation('testConvo2', bot);\n        botConvo2.ask('What is your favorite color?', async (response, convo, bot) => {\n            // noop\n        }, 'color');\n        botConvo2.say('ok you said {{vars.color}}');\n        bot.addDialog(botConvo2);\n\n        // set up a test client\n        const client = new BotkitTestClient('test', bot, ['testConvo', 'testConvo2']);\n\n        const prompt = await client.sendActivity('..');\n        assert(prompt.text === 'What is your name?', 'wrong prompt 1');\n\n        const prompt2 = await client.sendActivity('ben');\n        assert(prompt2.text === 'What is your favorite color?', 'wrong prompt 2');\n\n        const reply = await client.sendActivity('black');\n        assert(reply.text === 'ok you said black', 'wrong reply');\n\n        const reply2 = await client.getNextReply();\n        assert(reply2.text === 'got it.', 'wrong reply 2 in beginDialog test');\n    });\n\n\n    it('should navigate threads', async function() {\n        // test all the ways threads are triggered\n        // convo.gotoThread inside an ask\n        // convo.gotoThread inside an onChange\n        // addAction\n        // message with action field\n        // convo.gotoThread inside a beforeThread\n\n        const botConvo = new BotkitConversation('testConvo', bot);\n        let beforeThreadFired = false;\n        let beforeThread2Fired = false;\n        let beforeThread3Fired = false;\n        let beforeThread4Fired = false;\n        let beforeThread5Fired = false;\n        let beforeThread6Fired = false;\n\n        botConvo.say('1');\n        botConvo.addAction('thread-2');\n        botConvo.addMessage('2', 'thread-2');\n        botConvo.addQuestion('what?', async (response, convo, bot) => {\n            await convo.gotoThread('thread-3');\n        }, 'what', 'thread-2');\n        botConvo.addMessage('3', 'thread-3');\n        botConvo.addMessage('4', 'thread-4');\n        botConvo.addQuestion('what?', [], 'what2', 'thread-4');\n        botConvo.onChange('what2', async (response, convo, bot) => {\n            await convo.gotoThread('thread-5');\n        });\n        botConvo.addMessage('5', 'thread-5');\n        botConvo.addMessage({ text: 'next', action: 'thread-6' }, 'thread-5');\n        botConvo.addMessage('6', 'thread-6');\n\n        botConvo.before('default', async (convo, bot) => {\n            beforeThreadFired = true;\n        });\n\n        botConvo.before('thread-2', async (convo, bot) => {\n            beforeThread2Fired = true;\n        });\n        botConvo.before('thread-3', async (convo, bot) => {\n            beforeThread3Fired = true;\n            convo.gotoThread('thread-4');\n        });\n        botConvo.before('thread-4', async (convo, bot) => {\n            beforeThread4Fired = true;\n        });\n        botConvo.before('thread-5', async (convo, bot) => {\n            beforeThread5Fired = true;\n        });\n        botConvo.before('thread-6', async (convo, bot) => {\n            beforeThread6Fired = true;\n        });\n        bot.addDialog(botConvo);\n\n        // set up a test client\n        const client = new BotkitTestClient('test', bot, 'testConvo');\n\n        let prompt = await client.sendActivity('..');\n        assert(beforeThreadFired === true, 'beforeThread did not fire');\n        assert(prompt.text === '1', 'message 1 wrong');\n\n        prompt = await client.getNextReply();\n        assert(prompt.text === '2', 'message 2 wrong');\n        assert(beforeThread2Fired === true, 'before2Thread did not fire');\n\n        prompt = await client.getNextReply();\n        assert(prompt.text === 'what?', 'message 3 wrong');\n\n        prompt = await client.sendActivity('..');\n        assert(prompt.text === '4', 'message 4 wrong');\n        assert(beforeThread3Fired === true, 'before3Thread did not fire');\n        assert(beforeThread4Fired === true, 'before4Thread did not fire');\n\n        prompt = await client.getNextReply();\n        assert(prompt.text === 'what?', 'message 5 wrong');\n\n        prompt = await client.sendActivity('..');\n        assert(prompt.text === '5', 'message 6 wrong');\n        assert(beforeThread5Fired === true, 'before5Thread did not fire');\n\n        prompt = await client.getNextReply();\n        assert(prompt.text === 'next', 'message 7 wrong');\n        prompt = await client.getNextReply();\n        assert(prompt.text === '6', 'message 8 wrong');\n        assert(beforeThread6Fired === true, 'before6Thread did not fire');\n    });\n\n    it('should capture values correctly', async function() {\n        // capture with a simple ask\n        // capture with a child dialog\n\n        let correct = false;\n\n        let correct1 = false;\n        let correct2 = false;\n        let correct3 = false;\n        let correct4 = false;\n\n        const botConvo = new BotkitConversation('testConvo', bot);\n        const botConvo2 = new BotkitConversation('testConvo2', bot);\n\n        botConvo.ask('name', [], 'name');\n        botConvo.ask('color', [], 'color');\n        botConvo2.ask('location', [], 'location');\n        botConvo2.ask('preference', [], 'preference');\n        botConvo.addChildDialog('testConvo2', 'profile');\n\n        botConvo.onChange('name', async (response) => {\n            correct1 = response === 'name';\n        });\n        botConvo.onChange('color', async (response) => {\n            correct2 = response === 'color';\n        });\n        botConvo2.onChange('location', async (response) => {\n            correct3 = response === 'location';\n        });\n        botConvo2.onChange('preference', async (response) => {\n            correct4 = response === 'preference';\n        });\n\n        botConvo.after(async (results, bot) => {\n            correct = (results.name == 'name' && results.color == 'color' && results.profile.location == 'location' && results.profile.preference == 'preference');\n        });\n\n        bot.addDialog(botConvo);\n        bot.addDialog(botConvo2);\n\n        // set up a test client\n        const client = new BotkitTestClient('test', bot, ['testConvo', 'testConvo2']);\n\n        let msg = await client.sendActivity('..');\n        assert(msg.text == 'name', 'first prompt wrong');\n        msg = await client.sendActivity('name');\n        assert(msg.text == 'color', 'second prompt wrong');\n        msg = await client.sendActivity('color');\n        assert(msg.text == 'location', 'third prompt wrong');\n        msg = await client.sendActivity('location');\n        assert(msg.text == 'preference', 'fourth prompt wrong');\n        msg = await client.sendActivity('preference');\n        assert(correct, 'Value were NOT captured correctly');\n        assert(correct1, 'value 1 was correct during onchange');\n        assert(correct2, 'value 2 was correct during onchange');\n        assert(correct3, 'value 3 was correct during onchange');\n        assert(correct4, 'value 4 was correct during onchange');\n    });\n\n    it('should handle a series of child dialogs', async function() {\n\n        let correct = false;\n\n        const conversationChildDialogs = new BotkitConversation('child_dialogs', bot);\n        const conversationA = new BotkitConversation('A', bot);\n        const conversationB = new BotkitConversation('B', bot);\n        const conversationC = new BotkitConversation('C', bot);\n        const conversationD = new BotkitConversation('D', bot);\n\n        bot.addDialog(conversationChildDialogs);\n        bot.addDialog(conversationA);\n        bot.addDialog(conversationB);\n        bot.addDialog(conversationC);\n        bot.addDialog(conversationD);\n\n        conversationChildDialogs.addChildDialog('A');\n        conversationChildDialogs.addChildDialog('B');\n        conversationChildDialogs.addChildDialog('C');\n        conversationChildDialogs.addChildDialog('D');\n        conversationChildDialogs.after(async (results) => {\n            correct = (results.A.A == 'A') && (results.B.B == 'B') && (results.C.C == 'C') && (results.D.D=='D');\n        });\n\n        conversationA.ask({\n            text: ['A reply to me']\n        }, [\n            {\n                handler: async (response, convo, bot) => {\n                }\n            } ], 'A');\n\n        conversationB.ask({\n            text: ['B reply to me']\n        }, [\n            {\n                handler: async (response, convo, bot) => {\n                }\n            } ], 'B');\n\n        conversationC.ask({\n            text: ['C reply to me']\n        }, [\n            {\n                handler: async (response, convo, bot) => {\n                }\n            } ], 'C');\n\n        conversationD.ask({\n            text: ['D reply to me']\n        }, [\n            {\n                handler: async (response, convo, bot) => {\n                }\n            } ], 'D');\n\n        const client = new BotkitTestClient('test', bot, ['child_dialogs', 'A', 'B', 'C', 'D']);\n        let reply = await client.sendActivity('..');\n        assert(reply.text == 'A reply to me', 'A wrong');\n        reply = await client.sendActivity('A');\n        assert(reply.text == 'B reply to me', 'B wrong');\n        reply = await client.sendActivity('B');\n        assert(reply.text == 'C reply to me', 'C wrong');\n        reply = await client.sendActivity('C');\n        assert(reply.text == 'D reply to me', 'D wrong');\n        reply = await client.sendActivity('D');\n        assert(reply == null,'not null');\n        reply = await client.getNextReply();\n        assert(reply == null,'not null');\n        assert(correct,'results did not match expected format');\n    });\n\n    it('should allow cancel', async function() {\n\n        let after_fired = false;\n        const botConvo = new BotkitConversation('testConvo', bot);\n        botConvo.say('errr');\n        botConvo.say('boo');\n        botConvo.ask('huh?', async(response, convo, bot) => {\n            await bot.cancelAllDialogs();\n        },'wha');\n        botConvo.say('foo');\n        botConvo.after(async(results, bot) => {\n            after_fired = true;\n        });\n        bot.addDialog(botConvo);\n\n        // set up a test client\n        const client = new BotkitTestClient('test', bot, 'testConvo');\n        let msg = await client.sendActivity('..');\n        assert(msg.text == 'errr','no errr');\n        msg = await client.getNextReply();\n        assert(msg.text == 'boo','no boo');\n        msg = await client.getNextReply();\n        assert(msg.text == 'huh?', 'wrong prompt');\n        msg = await client.sendActivity('..');\n        assert(msg == null,'did not cancel');\n        msg = await client.getNextReply();\n        assert(msg == null,'did not cancel 2');\n        assert(after_fired === false, 'after fired after cancel');\n\n    });\n\n\n    it('should allow cancel inside child dialog', async function() {\n\n        let after_fired = false;\n        let after_fired2 = false;\n\n        const botConvo = new BotkitConversation('testConvo', bot);\n        const botConvo2 = new BotkitConversation('testConvo2', bot);\n        botConvo.say('hi');\n        botConvo.addChildDialog('testConvo2');\n        botConvo.say('foo');\n        botConvo2.ask('huh?', async(r, convo, bot) => {\n            await bot.cancelAllDialogs();\n        });\n        botConvo2.say('blarg');\n\n        botConvo.after(async(results, bot) => {\n            after_fired = true;\n        });\n        botConvo2.after(async(results, bot) => {\n            after_fired2 = true;\n        });\n\n        bot.addDialog(botConvo);\n        bot.addDialog(botConvo2);\n\n        // set up a test client\n        const client = new BotkitTestClient('test', bot, ['testConvo', 'testConvo2']);\n        let msg = await client.sendActivity('..');\n        assert(msg.text === 'hi', 'wrong msg 1');\n        msg = await client.getNextReply();\n        assert(msg.text == 'huh?', 'wrong msg 2');\n        msg = await client.sendActivity('..');\n        assert(msg == null, 'did not cancel');\n        assert(after_fired === false,'after dialog fired');\n        assert(after_fired2 === false,'after dialog of child fired');\n\n    });\n\n    it('should stop when convo.stop is called', async function() {\n\n        let after_fired = false;\n        const botConvo = new BotkitConversation('testConvo', bot);\n        botConvo.say('errr');\n        botConvo.say('boo');\n        botConvo.ask('huh?', async(response, convo, bot) => {\n            convo.stop();\n        },'wha');\n        botConvo.say('foo');\n        botConvo.after(async(results, bot) => {\n            after_fired = true;\n        });\n        bot.addDialog(botConvo);\n\n        // set up a test client\n        const client = new BotkitTestClient('test', bot, 'testConvo');\n        let msg = await client.sendActivity('..');\n        assert(msg.text == 'errr','no errr');\n        msg = await client.getNextReply();\n        assert(msg.text == 'boo','no boo');\n        msg = await client.getNextReply();\n        assert(msg.text == 'huh?', 'wrong prompt');\n        msg = await client.sendActivity('..');\n        assert(msg == null,'did not stop');\n        msg = await client.getNextReply();\n        assert(msg == null,'did not stop 2');\n        assert(after_fired === true, 'after fired after stop');\n\n    });\n\n    it('should call handlers for addQuestion and ask with entire message payload', async () => {\n        const conversation = new BotkitConversation('nameConvo', bot);\n\n        let correct1 = false;\n        let correct2 = false;\n        let correct3 = false;\n        let correct4 = false;\n        let correct5 = false;\n\n        conversation.ask(\n            'First name?',\n            async (response, convo, bot, message) => {\n                correct1 = message.type === ActivityTypes.Message && message.text === 'Tony' && response === message.text;\n                convo.gotoThread('last_name');\n            },\n            'firstName'\n        );\n        conversation.addQuestion(\n            'Last name?',\n            async (response, convo, bot, message) => {\n                correct2 = message.type === ActivityTypes.Message && message.text === 'Stark' && response === message.text;\n                convo.gotoThread('address');\n            },\n            'lastName',\n            'last_name'\n        );\n\n        conversation.addQuestion(\n            'Address?',\n            async (response, convo, bot, message) => {\n                correct3 = message.type === ActivityTypes.Message &&\n                    message.text === '10880 Malibu Point, 90265, Malibu, California' &&\n                    response === message.text;\n                convo.gotoThread('color');\n            },\n            'address',\n            'address'\n        );\n        conversation.addQuestion(\n            'Favourite Color?',\n            [\n                {\n                    default: true,\n                    handler: async (response, convo, bot, message) => {\n                        correct4 = message.type === ActivityTypes.Message && response === message.text;\n                        await convo.repeat();\n                    }\n                },\n                {\n                    pattern: 'Red',\n                    handler: async (response, convo, bot, message) => {\n                        correct5 = message.type === ActivityTypes.Message &&\n                            message.text === 'Red' && response === message.text;\n                        await convo.stop();\n                    }\n                }\n            ],\n            'color',\n            'color'\n        );\n\n        bot.addDialog(conversation);\n\n        // set up a test client\n        const client = new BotkitTestClient('test', bot, ['nameConvo']);\n\n        let msg = await client.sendActivity('..');\n        assert(msg.text === 'First name?', 'first prompt wrong');\n\n        msg = await client.sendActivity('Tony');\n        assert(msg.text === 'Last name?', 'second prompt wrong');\n\n        msg = await client.sendActivity('Stark');\n        assert(msg.text === 'Address?', 'third prompt wrong');\n\n        msg = await client.sendActivity('10880 Malibu Point, 90265, Malibu, California');\n        assert(msg.text === 'Favourite Color?', 'fourth prompt wrong');\n\n        msg = await client.sendActivity('Black');\n        assert(msg.text === 'Favourite Color?', 'repeat prompt wrong');\n\n        msg = await client.sendActivity('Red');\n\n        assert(correct1, 'message text not correct for prompt1');\n        assert(correct2, 'message text not correct for prompt2');\n        assert(correct3, 'message text not correct for prompt3');\n        assert(correct4, 'message text not correct for prompt4');\n        assert(correct5, 'message text not correct for prompt5');\n    });\n\n    afterEach(async () => {\n        await bot.shutdown();\n    });\n});"
  },
  {
    "path": "packages/botkit/tests/State.tests.js",
    "content": "const assert = require('assert');\nconst { BotkitConversationState } = require('../lib/conversationState');\nconst { MemoryStorage } = require('botbuilder');\n\nconst storage = new MemoryStorage();\nconst state = new BotkitConversationState(storage);\n\ndescribe('BotkitConversationState', function() {\n    it('should generate appropriate state key', function() {\n        const key = state.getStorageKey({\n            activity: {\n                channelId: 'test',\n                from: {\n                    id: 'foo'\n                },\n                conversation: {\n                    id: 'bar'\n                }\n            }\n        });\n        assert(key === 'test/conversations/bar-foo/', 'failed key gen');\n    });\n    it('should generate appropriate state key excluding properties field', function() {\n        const key = state.getStorageKey({\n            activity: {\n                channelId: 'test',\n                from: {\n                    id: 'foo'\n                },\n                conversation: {\n                    properties: {\n                        baz: true\n                    },\n                    id: 'bar'\n                }\n            }\n        });\n        assert(key === 'test/conversations/bar-foo/', 'failed key gen');\n    });\n    it('should generate appropriate state key including platform field', function() {\n        const key = state.getStorageKey({\n            activity: {\n                channelId: 'test',\n                from: {\n                    id: 'foo'\n                },\n                conversation: {\n                    threadId: '5',\n                    channel: '9',\n                    id: 'bar'\n                }\n            }\n        });\n        assert(key === 'test/conversations/9-bar-5-foo/', 'failed key gen');\n    });\n});\n"
  },
  {
    "path": "packages/botkit/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2015\",\n    \"module\": \"commonjs\",\n    \"declaration\": true,\n    \"sourceMap\": true,\n    \"outDir\": \"./lib\",\n    \"rootDir\": \"./src\",\n    \"types\" : [\"node\"],\n    \"lib\": [\n      \"es5\",\n      \"es2015\",\n      \"es2016.array.include\",\n      \"esnext.asynciterable\",\n      \"dom\"\n    ]\n  },\n  \"include\": [\n    \"src/**/*\"\n  ]\n}\n"
  },
  {
    "path": "packages/botkit-plugin-cms/.eslintrc.js",
    "content": "module.exports = {\n    \"extends\": \"standard\",\n    \"rules\": {\n        \"semi\": [2, \"always\"],\n        \"indent\": [2, 4],\n        \"no-return-await\": 0,\n        \"camelcase\": 0,\n        \"no-unused-vars\": 0,\n        \"@typescript-eslint/ban-ts-ignore\": 1,\n        \"@typescript-eslint/no-object-literal-type-assertion\": 0,\n        \"@typescript-eslint/indent\": 0,\n        \"@typescript-eslint/explicit-member-accessibility\": 1,\n        \"space-before-function-paren\": [2, {\n            \"named\": \"never\",\n            \"anonymous\": \"never\",\n            \"asyncArrow\": \"always\"\n        }],\n        \"template-curly-spacing\": [2, \"always\"]\n    }\n};"
  },
  {
    "path": "packages/botkit-plugin-cms/.gitignore",
    "content": "node_modules/\nlib/"
  },
  {
    "path": "packages/botkit-plugin-cms/CHANGELOG.md",
    "content": "# botkit-plugin-cms\n\n# botkit-plugin-cms changelog\n\n# 1.0.3\n\n* Emit a better error when an invalid token has been provided\n* Update dependencies (Bot Framework to 4.6, Botkit to 4.6)\n\n\n# 1.0.2\n\n* Update dependencies (Bot Framework to 4.5.2, Botkit to 4.5)\n* Improvements to reliability of the `uri` parameter on the constructor. \n\n\n# 1.0.1\n\n* Fix critical issue that causes CMS-powered dialogs to fail to load.\n\n# 1.0.0 \n\nthis was the initial release"
  },
  {
    "path": "packages/botkit-plugin-cms/LICENSE.md",
    "content": "Copyright XOXCO, Inc, http://xoxco.com, http://howdy.ai\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "packages/botkit-plugin-cms/package.json",
    "content": "{\n  \"name\": \"botkit-plugin-cms\",\n  \"version\": \"1.0.4\",\n  \"description\": \"Extend Botkit with access to botkit-cms\",\n  \"main\": \"./lib/index.js\",\n  \"typings\": \"./lib/index.d.ts\",\n  \"files\": [\n    \"/lib\",\n    \"/src\"\n  ],\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"eslint\": \"./node_modules/.bin/eslint --fix src/*\"\n  },\n  \"author\": \"benbrown@gmail.com\",\n  \"license\": \"MIT\",\n  \"keywords\": [\n    \"botkit\",\n    \"bots\",\n    \"chatbots\"\n  ],\n  \"homepage\": \"https://github.com/howdyai/botkit/blob/master/packages/botkit-plugin-cms#readme\",\n  \"bugs\": {\n    \"url\": \"https://github.com/howdyai/botkit/issues\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/howdyai/botkit.git\"\n  },\n  \"dependencies\": {\n    \"botkit\": \"^4.8.0\",\n    \"debug\": \"^4.1.0\"\n  },\n  \"devDependencies\": {\n    \"@types/express\": \"^4.17.2\",\n    \"@types/node\": \"^10.17.5\",\n    \"eslint\": \"^8.3.0\",\n    \"eslint-config-standard\": \"^16.0.3\",\n    \"eslint-plugin-import\": \"^2.25.3\",\n    \"eslint-plugin-node\": \"^11.1.0\",\n    \"eslint-plugin-promise\": \"^5.1.1\",\n    \"eslint-plugin-standard\": \"^4.0.1\"\n  }\n}\n"
  },
  {
    "path": "packages/botkit-plugin-cms/readme.md",
    "content": "# botkit-plugin-cms\n\nUse and extend dialogs authored remotely using [Botkit CMS](https://github.com/howdyai/botkit-cms#readme).\n\n## Install Package\n\nAdd this package to your project using npm:\n\n```bash\nnpm install --save botkit-plugin-cms\n```\n\nImport the adapter class into your code:\n\n```javascript\nconst { BotkitCMSHelper } = require('botkit-plugin-cms');\n```\n\n## Use in your App\n\nConfigure the plugin with the URI of your Botkit CMS instance and a token set in the CMS config.\nThese values are available from the cms admin dashboard's options tab.\n\nThen, register the plugin and it's features with the Botkit controller using `usePlugin()`\n\n```javascript\nlet cms = new BotkitCMSHelper({\n    uri: 'https://someurl.com/',\n    token: 'some-token-value'\n});\n\ncontroller.usePlugin(cms);\n```\n\nOnce registered, Botkit will automatically load all of the available content from the Botkit CMS api and dynamically create [BotkitConversation Dialogs](../docs/reference/core.md#botkitconversation) for use in The bot.  [All of the plugin's methods](../docs/reference/cms.md) will be available at `controller.plugins.cms`.\n\nTo evaluate all incoming messages for triggers configured in the CMS, and automatically respond by starting the appropriate dialog, use [controller.plugins.cms.testTrigger()](../docs/reference/cms.md#testtrigger):\n\n```javascript\n// use the cms to test remote triggers\ncontroller.on('message', async(bot, message) => {\n  let triggered = await controller.plugins.cms.testTrigger(bot, message);\n  \n  // if a script was triggered, return false from the handler.\n  // this stops botkit from any further processing.\n  if (triggered !== false) {\n      return false;\n  }\n});\n```\n\nIn most cases, calls to `testTrigger` should come at the _end_ of the bot's message evaluation process. Since Botkit fires handlers in the order in which they are added to the controller, this call should most often be placed _after_ other trigger definintions - particularly if the CMS has been configured with a fallback script which will ALWAYS fire even if no matching trigger is found.\n\n## Hooking code to your CMS-powered Dialogs\n\nSince under the hood, this plugin creates [BotkitConversation Dialogs](../docs/reference/core.md#botkitconversation), all of the same [hooks](../docs/conversations.md#hooks), [templating features](../docs/conversations.md#using-variable-tokens-and-templates-in-conversation-threads), and special actions are available. However, since the dialogs are built dynamically, special methods are necessary to _find the dialog by name_ within Botkit's collection of dialogs before binding hooks.\n\n* [controller.plugins.cms.before()](../docs/reference/cms.md#before)\n* [controller.plugins.cms.onChange()](../docs/reference/cms.md#onchange)\n* [controller.plugins.cms.after()](../docs/reference/cms.md#after)\n\nFor example, if the CMS has a script called `onboarding`, hook functions can be bound to it like so:\n\n```javascrit\n// wrap calls to the plugin in controller.ready to ensure the content has successfully loaded\ncontroller.ready(function() {\n\n    // fire before onboarding begins\n    controller.plugins.cms.before('onboarding', async(convo, bot) => {\n        convo.setVar('timestamp', new Date());\n    });\n\n    // fire after onboarding ends\n    controller.plugins.cms.after('onboarding', async(results, bot) => {\n        // do something like store results in the db\n\n        // take the next step...\n        await bot.say('ONBOARDING COMPLETE!');\n    });\n});\n```\n\n## Class Reference\n\n* [BotkitCMSHelper](../docs/reference/cms.md)\n\n## About Botkit\n\nBotkit is a part of the [Microsoft Bot Framework](https://dev.botframework.com).\n\nWant to contribute? [Read the contributor guide](https://github.com/howdyai/botkit/blob/master/CONTRIBUTING.md)\n\nBotkit is released under the [MIT Open Source license](https://github.com/howdyai/botkit/blob/master/LICENSE.md)"
  },
  {
    "path": "packages/botkit-plugin-cms/src/cms.ts",
    "content": "/**\n * @module botkit-plugin-cms\n */\n/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { Botkit, BotkitDialogWrapper, BotkitMessage, BotWorker, BotkitConversation } from 'botkit';\nimport * as request from 'request';\nimport * as Debug from 'debug';\nimport * as url from 'url';\n\nconst debug = Debug('botkit:cms');\n\n/**\n * A plugin for Botkit that provides access to an instance of [Botkit CMS](https://github.com/howdyai/botkit-cms), including the ability to load script content into a DialogSet\n * and bind before, after and onChange handlers to those dynamically imported dialogs by name.\n *\n * ```javascript\n * controller.use(new BotkitCMSHelper({\n *      uri: process.env.CMS_URI,\n *      token: process.env.CMS_TOKEN\n * }));\n *\n * // use the cms to test remote triggers\n * controller.on('message', async(bot, message) => {\n *   await controller.plugins.cms.testTrigger(bot, message);\n * });\n * ```\n */\nexport class BotkitCMSHelper {\n    private _config: any;\n    private _controller: Botkit;\n\n    /**\n     * Botkit Plugin name\n     */\n    public name = 'Botkit CMS';\n\n    public constructor(config: CMSOptions) {\n        this._config = config;\n        if (config.controller) {\n            this._controller = this._config.controller;\n        }\n\n        // for backwards compat, handle these alternate locations\n        if (this._config.cms_uri && !this._config.uri) {\n            this._config.uri = this._config.cms_uri;\n        }\n        if (this._config.cms_token && !this._config.token) {\n            this._config.token = this._config.cms_token;\n        }\n\n        if (!this._config.uri) {\n            throw new Error('Specify the root url of your Botkit CMS instance as `uri`');\n        }\n        if (!this._config.token) {\n            throw new Error('Specify a token that matches one configured in your Botkit CMS instance as `token`');\n        }\n    }\n\n    /**\n     * Botkit plugin init function\n     * Autoloads all scripts into the controller's main dialogSet.\n     * @param botkit A Botkit controller object\n     */\n    public init(botkit): void {\n        this._controller = botkit;\n        this._controller.addDep('cms');\n\n        // Extend the controller object with controller.plugins.cms\n        botkit.addPluginExtension('cms', this);\n\n        // pre-load all the scripts via the CMS api\n        this.loadAllScripts(this._controller).then(() => {\n            debug('Dialogs loaded from Botkit CMS');\n            this._controller.completeDep('cms');\n        }).catch((err) => {\n            console.error(`****************************************************************\\n${ err }\\n****************************************************************`);\n        });\n    }\n\n    private async apiRequest(uri: string, params: {[key: string]: any} = {}, method = 'GET'): Promise<any> {\n        const req = {\n            uri: new url.URL(uri + '?access_token=' + this._config.token, this._config.uri),\n            headers: {\n                'content-type': 'application/json'\n            },\n            method: method,\n            form: params\n        };\n\n        debug('Make request to Botkit CMS: ', req);\n\n        return new Promise((resolve, reject) => {\n            request(req, function(err, res, body) {\n                if (err) {\n                    debug('Error in Botkit CMS api: ', err);\n                    return reject(err);\n                } else {\n                    debug('Raw results from Botkit CMS: ', body);\n                    if (body === 'Invalid access token') {\n                        return reject(new Error('Failed to load Botkit CMS content: Invalid access token provided.\\nMake sure the token passed into the CMS plugin matches the token set in the CMS .env file.'));\n                    }\n                    let json = null;\n                    try {\n                        json = JSON.parse(body);\n                    } catch (err) {\n                        debug('Error parsing JSON from Botkit CMS api: ', err);\n                        return reject(err);\n                    }\n\n                    if (!json || json == null) {\n                        reject(new Error('Botkit CMS API response was empty or invalid JSON'));\n                    } else if (json.error) {\n                        if (res.statusCode === 401) {\n                            console.error(json.error);\n                        }\n                        reject(json.error);\n                    } else {\n                        resolve(json);\n                    }\n                }\n            });\n        });\n    }\n\n    private async getScripts(): Promise<any[]> {\n        return this.apiRequest('/api/v1/commands/list');\n    }\n\n    private async evaluateTrigger(text: string): Promise<any> {\n        return this.apiRequest('/api/v1/commands/triggers', {\n            triggers: text\n        }, 'POST');\n    }\n\n    /**\n     * Load all script content from the configured CMS instance into a DialogSet and prepare them to be used.\n     * @param dialogSet A DialogSet into which the dialogs should be loaded.  In most cases, this is `controller.dialogSet`, allowing Botkit to access these dialogs through `bot.beginDialog()`.\n     */\n    public async loadAllScripts(botkit: Botkit): Promise<void> {\n        const scripts = await this.getScripts();\n\n        scripts.forEach((script) => {\n            // map threads from array to object\n            const threads = {};\n            script.script.forEach((thread) => {\n                threads[thread.topic] = thread.script.map(this.mapFields);\n            });\n\n            const d = new BotkitConversation(script.command, this._controller);\n            d.script = threads;\n            botkit.addDialog(d);\n        });\n    }\n\n    /**\n     * Map some less-than-ideal legacy fields to better places\n     */\n    private mapFields(line): void {\n        // Create the channelData field where any channel-specific stuff goes\n        if (!line.channelData) {\n            line.channelData = {};\n        }\n\n        // TODO: Port over all the other mappings\n\n        // move slack attachments\n        if (line.attachments) {\n            line.channelData.attachments = line.attachments;\n        }\n\n        // we might have a facebook attachment in fb_attachments\n        if (line.fb_attachment) {\n            const attachment = line.fb_attachment;\n            if (attachment.template_type) {\n                if (attachment.template_type === 'button') {\n                    attachment.text = line.text[0];\n                }\n                line.channelData.attachment = {\n                    type: 'template',\n                    payload: attachment\n                };\n            } else if (attachment.type) {\n                line.channelData.attachment = attachment;\n            }\n\n            // blank text, not allowed with attachment\n            line.text = null;\n\n            // remove blank button array if specified\n            if (line.channelData.attachment.payload.elements) {\n                for (let e = 0; e < line.channelData.attachment.payload.elements.length; e++) {\n                    if (!line.channelData.attachment.payload.elements[e].buttons || !line.channelData.attachment.payload.elements[e].buttons.length) {\n                        delete (line.channelData.attachment.payload.elements[e].buttons);\n                    }\n                }\n            }\n\n            delete (line.fb_attachment);\n        }\n\n        // Copy quick replies to channelData.\n        // This gives support for both \"native\" quick replies AND facebook quick replies\n        if (line.quick_replies) {\n            line.channelData.quick_replies = line.quick_replies;\n        }\n\n        // handle teams attachments\n        if (line.platforms && line.platforms.teams) {\n            if (line.platforms.teams.attachments) {\n                line.attachments = line.platforms.teams.attachments.map((a) => {\n                    a.content = { ...a };\n                    a.contentType = 'application/vnd.microsoft.card.' + a.type;\n                    return a;\n                });\n            }\n            delete (line.platforms.teams);\n        }\n\n        // handle additional custom fields defined in Botkit-CMS\n        if (line.meta) {\n            for (let a = 0; a < line.meta.length; a++) {\n                line.channelData[line.meta[a].key] = line.meta[a].value;\n            }\n            delete (line.meta);\n        }\n\n        return line;\n    }\n\n    /**\n     * Uses the Botkit CMS trigger API to test an incoming message against a list of predefined triggers.\n     * If a trigger is matched, the appropriate dialog will begin immediately.\n     * @param bot The current bot worker instance\n     * @param message An incoming message to be interpretted\n     * @returns Returns false if a dialog is NOT triggered, otherwise returns void.\n     */\n    public async testTrigger(bot: BotWorker, message: Partial<BotkitMessage>): Promise<any> {\n        const command = await this.evaluateTrigger(message.text);\n        if (command.command) {\n            return await bot.beginDialog(command.command);\n        }\n        return false;\n    }\n\n    /**\n     * Bind a handler function that will fire before a given script and thread begin.\n     * Provides a way to use BotkitConversation.before() on dialogs loaded dynamically via the CMS api instead of being created in code.\n     *\n     * ```javascript\n     * controller.cms.before('my_script','my_thread', async(convo, bot) => {\n     *\n     *  // do stuff\n     *  console.log('starting my_thread as part of my_script');\n     *  // other stuff including convo.setVar convo.gotoThread\n     *\n     * });\n     * ```\n     *\n     * @param script_name The name of the script to bind to\n     * @param thread_name The name of a thread within the script to bind to\n     * @param handler A handler function in the form async(convo, bot) => {}\n     */\n    public before(script_name: string, thread_name: string, handler: (convo: BotkitDialogWrapper, bot: BotWorker) => Promise<void>): void {\n        const dialog = this._controller.dialogSet.find(script_name) as BotkitConversation;\n        if (dialog) {\n            dialog.before(thread_name, handler);\n        } else {\n            throw new Error('Could not find dialog: ' + script_name);\n        }\n    }\n\n    /**\n     * Bind a handler function that will fire when a given variable is set within a a given script.\n     * Provides a way to use BotkitConversation.onChange() on dialogs loaded dynamically via the CMS api instead of being created in code.\n     *\n     * ```javascript\n     * controller.plugins.cms.onChange('my_script','my_variable', async(new_value, convo, bot) => {\n    *\n    * console.log('A new value got set for my_variable inside my_script: ', new_value);\n    *\n    * });\n    * ```\n    *\n    * @param script_name The name of the script to bind to\n    * @param variable_name The name of a variable within the script to bind to\n    * @param handler A handler function in the form async(value, convo, bot) => {}\n    */\n    public onChange(script_name: string, variable_name: string, handler: (value: any, convo: BotkitDialogWrapper, bot: BotWorker) => Promise<void>): void {\n        const dialog = this._controller.dialogSet.find(script_name) as BotkitConversation;\n        if (dialog) {\n            dialog.onChange(variable_name, handler);\n        } else {\n            throw new Error('Could not find dialog: ' + script_name);\n        }\n    }\n\n    /**\n    * Bind a handler function that will fire after a given dialog ends.\n    * Provides a way to use BotkitConversation.after() on dialogs loaded dynamically via the CMS api instead of being created in code.\n    *\n    * ```javascript\n    * controller.plugins.cms.after('my_script', async(results, bot) => {\n    *\n    * console.log('my_script just ended! here are the results', results);\n    *\n    * });\n    * ```\n    *\n    * @param script_name The name of the script to bind to\n    * @param handler A handler function in the form async(results, bot) => {}\n    */\n    public after(script_name: string, handler: (results: any, bot: BotWorker) => Promise<void>): void {\n        const dialog = this._controller.dialogSet.find(script_name) as BotkitConversation;\n        if (dialog) {\n            dialog.after(handler);\n        } else {\n            throw new Error('Could not find dialog: ' + script_name);\n        }\n    }\n}\n\nexport interface CMSOptions {\n    uri: string;\n    token: string;\n    controller?: Botkit;\n}\n"
  },
  {
    "path": "packages/botkit-plugin-cms/src/index.ts",
    "content": "/**\n * @module botkit-plugin-cms\n */\n/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport * from './cms';\n"
  },
  {
    "path": "packages/botkit-plugin-cms/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2015\",\n    \"module\": \"commonjs\",\n    \"declaration\": true,\n    \"sourceMap\": true,\n    \"outDir\": \"./lib\",\n    \"rootDir\": \"./src\",\n    \"types\" : [\"node\"],\n    \"lib\": [\n      \"es5\",\n      \"es2015\",\n      \"es2016.array.include\",\n      \"esnext.asynciterable\",\n      \"dom\"\n    ]\n  },\n  \"include\": [\n    \"src/**/*\"\n  ]\n}"
  },
  {
    "path": "packages/docs/.gitignore",
    "content": "build/*.json\n"
  },
  {
    "path": "packages/docs/advanced.md",
    "content": "# Advanced topics\n\n## What causes the error: `UnhandledPromiseRejectionWarning: TypeError: Cannot perform 'get' on a proxy that has been revoked`\n\nThis happens when a call to bot.say, bot.reply, or bot.beginDialog has been used without the `await` keyword.\n\nMake sure you `await` all calls to these and similar functions! These functions return promises that have to be resolved\nproperly, otherwise you'll get the above error!\n\n## Botkit 4.0 Goals:\n\nThese were the goals we set out to achieve in creating the new version of Botkit.\n\n* Keep as much of the feature set, syntax and special sauce developers know and love\n* Solve persistent and hard to solve problems in previous versions of Botkit\n* Use modern JavaScript language features like async/await instead of callbacks\n* Full Typescript support\n* Break platform adapters (and their large dependency trees) into optional packages\n* Reorganize some related projects into a monorepo\n* Inherit much goodness from [Bot Framework SDK](https://github.com/microsoft/botbuilder-js)\n* Provide a way for bots to be extended with plugins and modular features, and for those plugins to provide a consistent interface to administrators\n\n\n## What's different between 0.7 and 4.0?\n\nThe [changelog](https://github.com/howdyai/botkit/blob/master/changelog.md#401) has lots of details on the new features.\n\nIn addition, here are some notes on the major changes:\n\n* All of the major features now uses promises and the async/await pattern. Goodbye, nested callbacks!\n* Everything has been rebuilt using Typescript classes. If you want types, you got 'em!\n* The dialog system has been rearchitected to solve some long term issues - but much of the familiar syntax has been retained.\n* The core Botkit library now contains just the platform-independent APIs for building bot features. Platform adapters are now separate modules.\n* Botkit is now inherits core classes from [Bot Framework SDK](https://github.com/microsoft/botframework-sdk#readme) and as a result gains compatibility with all of the tools from Bot Framework - in particular [dialogs](https://npmjs.com/package/botbuilder-dialogs) and [Bot Framework Emulator](https://aka.ms/botframework-emulator)\n* Botkit no longer provides a generic \"storage\" layer. Developers will need to build their own or use a hybrid approach (see below.)\n\n\n## How to upgrade from 0.7 to 4.0\n\nThough many things have changed in the latest version of Botkit, and it is not directly backwards compatible with previous versions,\nmany elements of the previous Botkit syntax are still present and the vast majority of features from the previous versions.\nExperienced Botkit developers will recognize the familiar syntax of features like `hears()` and `ask()`.\n\nThe overall structure of the Botkit application is roughly the same, though the shape of some components have shifted.\nBefore upgrading your bot, use the yeoman generator to create a sample app -- if only to understand its structure.\nIn most cases, the best approach will be to create a new bot using the generator, then port existing \"skill\" files to the new syntax.\n\nYou may need to update your Node version because v4 of Botkit uses modern Javascript syntax. We suggest using the LTS version.\n\n### Changes to how Botkit is installed and configured:\n\n* Previous versions of Botkit contained all the adapters. Now the adapters are separate packages.\n* Now have to separately configure Botkit and the adapter.\n* If you previously used a starter kit,  the easiest way is to start with a new yeoman generator template, then copy over skill files, then make some syntax updates.\n\nFROM:\n```\nvar Botkit = require('botkit');\n\nvar controller = new Botkit.slackbot(options);\n```\n\nTO:\n```\nconst { Botkit } = require('botkit');\nconst { SlackAdapter } = require('botbuilder-adapter-slack');\n\nlet adapter = new SlackAdapter(options);\nlet controller = new Botkit({\n    adapter: adapter\n});\n```\n\n### Syntax changes in your bot code:\n\n* Everything has been promisified! Before all your \"hears\" or \"on\" handlers, add the \"async\" keyword to the function.\n* Add \"await\" keyword in front of all calls to bot.reply or bot.say or similar functions.\n* The name of the event for normal messages has changed.  Change any instance of 'message_received' to 'message'\n\nFROM:\n```\nbot.hears('foo', 'message_received', function(bot, message) { \n    bot.reply(message,'bar');\n});\n```\n\nTO:\n```\nbot.hears('foo', 'message', async(bot, message) => { \n    await bot.reply(message,'bar');\n});\n```\n\n### Conversation changes:\n\n* All conversations have to be constructed using `new BotkitConversation()` added using `controller.addDialog()` at startup (not inside handler or dynamically)\n* Any call to startConversation (and related functions) has to be updated - these functions still exist but work differently, and must be paired with a call to `bot.beginDialog()`\n* The new system no longer has support for modifying the conversation structure on the fly by doing additional calls to convo.say or convo.ask from inside callbacks. If your dialog requires sending ad hoc messages, it is still possible to do that using use `bot.say()` rather than `convo.say()`\n* The syntax for convo.ask and convo.say remains mostly the same\n* convo.ask handlers are now in the format `async(response, convo, bot)=>{}`. as a result of these being promises, it is no longer necessary to call convo.next\n* Hook functions have changed a bit: convo.before takes a thread name, to fire before anything, set that to default.\n\nFROM:\n```\nbot.hears('tacos', 'direct_message', function(bot, message) {\n    bot.startConversation(function(err, convo) { \n\n        convo.say('SOMEONE SAID TACOS!');\n        convo.ask('Do you want to eat a taco?', [\n            {\n                pattern: 'yes',\n                default: true,\n                callback: function(response, convo) {\n                    convo.gotoThread('yes_tacos');\n                }\n            },\n            {\n                pattern: 'no',\n                callback: function(response, convo) {\n                    convo.gotoThread('no_tacos');\n                }\n            }\n        ], {key: 'wants_taco'});\n\n        convo.addMessage('Hooray for tacos!', 'yes_tacos');\n        convo.addMessage('ERROR: Tacos missing!!', 'no_tacos');\n\n        convo.on('end', function(convo) {\n            var responses = convo.extractResponses();\n            // responses.wants_tacos\n        });\n    });\n});\n```\n\nTO:\n```\nconst { BotkitConversation } = require('botkit');\n\nlet convo = new BotkitConversation('tacos', controller);\nconvo.say('SOMEONE SAID TACOS!');\nconvo.ask('Do you want to eat a taco?', [\n    {\n        pattern: 'yes',\n        default: true,\n        handler: async(response, convo, bot) => {\n            await convo.gotoThread('yes_tacos');\n        }\n    },\n    {\n        pattern: 'no',\n        handler: async(response, convo, bot) => {\n            await convo.gotoThread('no_tacos');\n        }\n    }\n], 'wants_taco');\n\nconvo.addMessage('Hooray for tacos!', 'yes_tacos');\nconvo.addMessage('ERROR: Tacos missing!!', 'no_tacos');\n\nconvo.after(async(results, bot) => {\n\n    // results.wants_taco\n\n})\n\n// add to the controller to make it available for later.\ncontroller.addDialog(convo);\n\ncontroller.hears('tacos', 'direct_message', async(bot, message) => {\n    await bot.beginDialog('tacos');\n});\n```\n\n### Botkit Studio / Botkit CMS changes:\n\nThe functionality previously associated with Botkit Studio and now associated with Botkit CMS has been now been moved out of the core SDK\nand into a plugin module.\n\nTo access dialog content build in Botkit CMS, install `botkit-plugin-cms`, and adjust calls to the CMS from `controller.studio.*` to `controller.plugins.cms.*`:\n\n* `controller.studio.before('script', ...)` becomes `controller.plugins.cms.before('script', 'default', ...)`\n* `controller.studio.beforeThread('script', 'thread')` becomes `controller.plugins.cms.before('script', 'thread', ...)`\n* `controller.studio.after('script', ...)` becomes `controller.plugins.cms.after('script', ...)`\n* `controller.studio.validate('script', 'variable', ...')` becomes `controller.plugins.cms.onChange('script', 'variable', ...)`\n\nRead [more about using botkit-plugin-cms here](plugins/cms.html)\n\n### Storage changes\n\nIn v4 of Botkit, the storage system is currently only used to store and retrieve the conversation state between turns.\nOther than this, Botkit will no longer be providing an interface for connecting to or using databases. Developers\nshould build their own database abstractions.\n\nHowever to reduce the complexity of the upgrade process, existing bots can continue to use storage adapters from \nprevious versions of Botkit using [the technique discussed here](https://github.com/howdyai/botkit-storage-mongo/issues/42#issuecomment-489654424).\n\n\n## Anatomy of a Botkit App\n\nFile structure:\n\n* main app file (normally bot.js)\n* features/ folder\n* .env file\n* package.json file\n\nin bot.js:\n\n* create adapter\n* create botkit\n* load any middlewares or plugins\n* use `controller.loadModules()` to load features/ folder\n\nin features/ folder:\n\nmodules in the form:\n\n```javascript\nmodule.exports = function(controller) {\n    // some code here.\n}\n```\n## Flow of activity as a message is processed\n\n* Adapter receives incoming http request\n* Activity object is created, passed off to Botkit\n* Botkit turns the Activity object into a BotkitMessage\n* Botkit runs ingest middleware\n* Botkit evaluates for interrupts -> end if triggered\n* Botkit passes to dialog stack -> end if active dialog \n* Botkit evaluates for hears -> end if triggered\n* Botkit runs receive middleware\n* Botkit emits an event based on the `type` field of the message\n* Any handlers bound to event fire\n* Adapter sends http response\n\nWhen a message is sent:\n\n* Botkit receives message from code\n* Botkit runs send middleware\n* Activity object is created, passed off to BotBuilder\n* BotBuilder sends the message to the platform API\n\n## How to use \"Bot Inspector\" mode\n\nWith Bot Inspector mode enabled, you can use [Bot Framework Emulator](https://aka.ms/botframework-emulator) to\nconnect to your bot _while it also sends and receives messages to the live platform of your choice._ Once activated,\nyou'll be able to inspect the JSON payloads of incoming and outgoing messages, as well as inspect your bot's state variables.\n\nIt is TRULY COOL AND USEFUL, like opening an access panel into your bot's brain and being able to poke around like they did with Data on Star Trek: The Next Generation.\n\nTo enable this in a Botkit app:\n\n* Add [this module](https://gist.github.com/benbrown/d6fbf2c8aac37b60c746abc08b9b96e7) to your app.\n* Download the latest [Bot Framework Emulator](https://aka.ms/botframework-emulator)\n* Launch your bot app and make sure it is connected to the outside world with a tool like ngrok\n* Launch Bot Framework emulator and enable inspector mode \"View > Bot Inspector Mode\" in the menu\n* Connect to \"http://localhost:3000/api/sidecar\"\n* Bot Framework emulator will display a command like \"/INSPECT attach XYZ\".  Copy paste this into the channel with your bot that you want to inspect.\n* If successful, your bot should respond automatically.\n* Watch the emulator for future messages between your bot and the channel being inspected.\n\n\n## Typescript\n\ncoming \n\n## How to build a new adapter\n\ncoming\n"
  },
  {
    "path": "packages/docs/build/adapter.hbs",
    "content": "[&larr; Botkit Documentation](../core.md)  [&larr; Platform Index](index.md) \n\n{{{body}}}\n"
  },
  {
    "path": "packages/docs/build/build.sh",
    "content": "#!/bin/sh\n# generate main docs\n./node_modules/.bin/typedoc --excludePrivate  --ignoreCompilerErrors --module amd --hideGenerator --name \"Botkit Core\" --readme none --entryPoint botkit ../botkit/src/index.ts --json build/botkit.json\n./node_modules/.bin/typedoc --excludePrivate  --ignoreCompilerErrors --module amd --hideGenerator --name \"Botkit for Slack\" --readme none --entryPoint \"botbuilder-adapter-slack\" ../botbuilder-adapter-slack/src/index.ts --json build/slack.json\n./node_modules/.bin/typedoc --excludePrivate  --ignoreCompilerErrors --module amd --hideGenerator --name \"Botkit for Facebook\" --readme none --entryPoint \"botbuilder-adapter-facebook\" ../botbuilder-adapter-facebook/src/index.ts --json build/facebook.json\n./node_modules/.bin/typedoc --excludePrivate  --ignoreCompilerErrors --module amd --hideGenerator --name \"Botkit for Hangouts\" --readme none --entryPoint \"botbuilder-adapter-hangouts\" ../botbuilder-adapter-hangouts/src/index.ts --json build/hangouts.json\n./node_modules/.bin/typedoc --excludePrivate  --ignoreCompilerErrors --module amd --hideGenerator --name \"Botkit for Twilio SMS\" --readme none --entryPoint \"botbuilder-adapter-twilio-sms\" ../botbuilder-adapter-twilio-sms/src/index.ts --json build/twilio-sms.json\n./node_modules/.bin/typedoc --excludePrivate  --ignoreCompilerErrors --module amd --hideGenerator --name \"Botkit for Webex Teams\" --readme none --entryPoint \"botbuilder-adapter-webex\" ../botbuilder-adapter-webex/src/index.ts --json build/webex.json\n./node_modules/.bin/typedoc --excludePrivate  --ignoreCompilerErrors --module amd --hideGenerator --name \"Botkit for the Web\" --readme none --entryPoint \"botbuilder-adapter-web\" ../botbuilder-adapter-web/src/index.ts --json build/web.json\n./node_modules/.bin/typedoc --excludePrivate  --ignoreCompilerErrors --module amd --hideGenerator --name \"Botkit CMS Plugin\" --readme none --entryPoint \"botkit-plugin-cms\" ../botkit-plugin-cms/src/index.ts --json build/cms.json\n\nnode build/parse.js\n"
  },
  {
    "path": "packages/docs/build/parse.js",
    "content": "const fs = require('fs');\nconst Handlebars = require('handlebars');\nlet markup = fs.readFileSync(__dirname + '/template.hbs','utf8');\n\n// get rid of leading whitepsace on every line\nmarkup = markup.replace(/^ +/img,'');\nconst template = Handlebars.compile(markup);\n\nlet index = [];\nlet adapters = [];\nlet plugins = [];\n\nHandlebars.registerHelper('no-newline', function(str) {\n    if (str) {\n        return new Handlebars.SafeString(\n            str.replace(/\\n/g,'<br/>')\n        );\n    } else { \n        return '';\n    }\n});\n\nfunction buildTOC(dest) {\n\n    let toctemplate = Handlebars.compile(fs.readFileSync(__dirname + '/toc.hbs', 'utf8'));\n    console.log(JSON.stringify(index, null, 2));\n    fs.writeFileSync(dest, toctemplate({index: index, title: 'Class Index'}));\n}\n\nfunction buildAdapters(dest) {\n\n    let toctemplate = Handlebars.compile(fs.readFileSync(__dirname + '/toc-platforms.hbs', 'utf8'));\n    console.log(JSON.stringify(index, null, 2));\n    fs.writeFileSync(dest, toctemplate({index: adapters, title: 'Platform Adapters'}));\n}\n\nfunction buildPlugins(dest) {\n\n    let toctemplate = Handlebars.compile(fs.readFileSync(__dirname + '/toc.hbs', 'utf8'));\n    console.log(JSON.stringify(index, null, 2));\n    fs.writeFileSync(dest, toctemplate({index: plugins, title: 'Botkit Plugins'}));\n}\n\nfunction buildIndex(dest) {\n\n    fs.writeFileSync(dest,JSON.stringify({\n        reference: index,\n        adapters: adapters,\n        plugins: plugins\n    }, null, 2));\n\n}\n\n\nfunction generateAdapter(src, params, dest) {\n\n    let data = {\n        body: fs.readFileSync(src, 'utf8'),\n        ...params\n    };\n\n    // replace links\n    data.body = data.body.replace(/\\.\\.\\/docs\\/reference/ig,'../reference');\n    data.body = data.body.replace(/\\.\\.\\/docs/ig,'..');\n\n    let adaptertemplate = Handlebars.compile(fs.readFileSync(__dirname + '/adapter.hbs', 'utf8'));\n\n    fs.writeFileSync(dest, adaptertemplate(data));\n\n    adapters.push(\n        {\n            name: data.name,\n            path: dest.replace(/.*?\\/(platforms\\/.*)/,'$1'),\n        }\n    );\n}\n\n\nfunction generatePlugin(src, params, dest) {\n\n    let data = {\n        body: fs.readFileSync(src, 'utf8'),\n        ...params\n    };\n\n    // replace links\n    data.body = data.body.replace(/\\.\\.\\/docs\\/reference/ig,'../reference');\n    data.body = data.body.replace(/\\.\\.\\/docs/ig,'..');\n\n    let adaptertemplate = Handlebars.compile(fs.readFileSync(__dirname + '/plugin.hbs', 'utf8'));\n\n    fs.writeFileSync(dest, adaptertemplate(data));\n\n    plugins.push(\n        {\n            name: data.name,\n            path: dest.replace(/.*?\\/(plugins\\/.*)/,'$1'),\n        }\n    );\n}\n\nfunction generateReference(src, dest) {\n\n    let data = require(src);\n\n    let classes = [];\n\n    let interfaces = [];\n\n    for (var m = 0; m < data.children.length; m++) {\n        let module = data.children[m];\n\n        // find the classes\n        for (var c = 0; c < module.children.length; c++) {\n            let aclass = module.children[c];\n            if (aclass.kindString === 'Class') {\n                // console.log('>',aclass.name, aclass.kindString);\n                if (aclass.children) {\n                    aclass.props = aclass.children.filter((c) => { return c.kindString === 'Property' });\n                    aclass.props = [...aclass.props, ...aclass.children.filter((c) => { return c.kindString === 'Accessor' })];\n\n                    // controller.middleware is an object literal\n                    // aclass.props = [...aclass.props, ...aclass.children.filter((c) => { return c.kindString === 'Object literal' })];\n\n                    aclass.methods = aclass.children.filter((c) => { return c.kindString === 'Method' });\n                    aclass.constructors = aclass.children.filter((c) => { return c.kindString === 'Constructor' });\n                }\n                classes.push(aclass);\n            } else if (aclass.kindString === 'Interface') {\n                if (aclass.children) {\n                    aclass.props = aclass.children.filter((c) => { return c.kindString === 'Property' });\n                }\n                interfaces.push(aclass);\n            }\n        }\n    }\n\n    classes = classes.sort(sortByName);\n    interfaces = interfaces.sort(sortByName);\n\n    // first float the botworker class if present to top\n    classes = classes.sort(workerAtTop);\n\n    // now float adapter to top.  should result in Adapter, Worker, other classes\n    classes = classes.sort(adapterAtTop);\n\n    classes = classes.sort(botkitAtTop);\n\n    // console.log(module.name, module.kindString, module.children.length);\n    index.push(\n        {\n            name: data.name,\n            packageName: data.children[0].name,\n            path: dest.replace(/.*?\\/(reference\\/.*)/,'$1'),\n            classes: classes,\n            interfaces: interfaces\n        }\n    );\n\n    fs.writeFileSync(dest, template({classes: classes, interfaces: interfaces, packageName: data.children[0].name, name: data.name }));\n}\n\nfunction sortByName(a,b) {\n    if(a.name < b.name) { return -1; }\n    if(a.name > b.name) { return 1; }\n    return 0;\n}\n\nfunction botkitAtTop(a,b) {\n    if (a.name.match(/^botkit$/i)) { \n        return -1;\n    } else if(b.name.match(/^botkit$/i)) {\n        return 1;\n    } else {\n        return 0;\n    }\n}\n\n\nfunction workerAtTop(a,b) {\n    if (a.name.match(/botworker/i)) { \n        return -1;\n    } else if(b.name.match(/botworker/i)) {\n        return 1;\n    } else {\n        return 0;\n    }\n}\n\n\nfunction adapterAtTop(a,b) {\n    if (a.name.match(/adapter/i)) { \n        return -1;\n    } else if(b.name.match(/adapter/i)) {\n        return 1;\n    } else {\n        return 0;\n    }\n}\n\ngenerateReference(__dirname + '/botkit.json',__dirname + '/../reference/core.md');\ngenerateReference(__dirname + '/web.json',__dirname + '/../reference/web.md');\ngenerateReference(__dirname + '/webex.json',__dirname + '/../reference/webex.md');\ngenerateReference(__dirname + '/slack.json',__dirname + '/../reference/slack.md');\ngenerateReference(__dirname + '/hangouts.json',__dirname + '/../reference/hangouts.md');\ngenerateReference(__dirname + '/twilio-sms.json',__dirname + '/../reference/twilio-sms.md');\ngenerateReference(__dirname + '/facebook.json',__dirname + '/../reference/facebook.md');\ngenerateReference(__dirname + '/cms.json',__dirname + '/../reference/cms.md');\n\ngenerateAdapter(__dirname + '/../../botbuilder-adapter-web/readme.md', {name: 'Websocket and Webhooks'} , __dirname + '/../platforms/web.md');\ngenerateAdapter(__dirname + '/../../botbuilder-adapter-webex/readme.md', {name: 'Webex Teams'} , __dirname + '/../platforms/webex.md');\ngenerateAdapter(__dirname + '/../../botbuilder-adapter-slack/readme.md', {name: 'Slack'} , __dirname + '/../platforms/slack.md');\ngenerateAdapter(__dirname + '/../../botbuilder-adapter-hangouts/readme.md', {name: 'Google Hangouts'} , __dirname + '/../platforms/hangouts.md');\ngenerateAdapter(__dirname + '/../../botbuilder-adapter-twilio-sms/readme.md', {name: 'Twilio SMS'} , __dirname + '/../platforms/twilio-sms.md');\ngenerateAdapter(__dirname + '/../../botbuilder-adapter-facebook/readme.md', {name: 'Facebook Messenger'} , __dirname + '/../platforms/facebook.md');\n\ngeneratePlugin(__dirname + '/../../botkit-plugin-cms/readme.md', {name: 'Botkit CMS Plugin'} , __dirname + '/../plugins/cms.md');\n\n\nbuildTOC(__dirname + '/../reference/index.md');\nbuildAdapters(__dirname + '/../platforms/index.md');\nbuildPlugins(__dirname + '/../plugins/index.md');\nbuildIndex(__dirname + '/../index.json');"
  },
  {
    "path": "packages/docs/build/plugin.hbs",
    "content": "[&larr; Botkit Documentation](../core.md)  [&larr; Plugin Index](index.md) \n\n{{{body}}}"
  },
  {
    "path": "packages/docs/build/template.hbs",
    "content": "# {{name}} Class Reference\n\n[&larr; Botkit Documentation](../core.md) [&larr; Class Index](index.md) \n\nThis is a class reference for all the methods exposed by the [{{packageName}}](https://github.com/howdyai/botkit/tree/master/packages/{{packageName}}) package.\n\n## Classes\n\n{{#each classes}}{{#if flags.isExported}}\n* <a href=\"#{{name}}\" aria-current=\"page\">{{name}}</a>{{/if}}{{/each}}\n\n{{#if interfaces.length}}\n## Interfaces\n{{#each interfaces}}{{#if flags.isExported}}\n* <a href=\"#{{name}}\" aria-current=\"page\">{{name}}</a>{{/if}}{{/each}}\n{{/if}}\n\n---\n\n{{#each classes}}\n{{#if flags.isExported}}\n<a name=\"{{name}}\"></a>\n## {{name}}\n{{{comment.shortText}}}\n{{#if comment.text}}\n\n{{{comment.text}}}\n{{/if}}\n\nTo use this class in your application, first install the package:\n```bash\nnpm install --save {{../packageName}}\n```\n\nThen import this and other classes into your code:\n```javascript\nconst { {{name}} } = require('{{../packageName}}');\n```\n\n{{#if methods.length}}\n    This class includes the following methods:\n    {{#each methods}}\n    * [{{name}}()](#{{name}})\n    {{/each}}\n{{/if}}\n\n\n\n    {{#each constructors}}\n        {{#each signatures}}\n            ### Create a {{name}}()\n            {{#if parameters}}\n                **Parameters**\n\n                | Argument | Type | Description\n                |--- |--- |---\n                {{#each parameters}}\n                | {{name}} | {{#if type.id}}[{{type.name}}](#{{type.name}}){{else}}{{type.name}}{{/if}}{{#if type.typeArguments}}&lt;{{type.typeArguments.[0].name}}&gt;{{/if}} | {{#if comment.text}}{{{no-newline comment.text}}}{{else}}{{{no-newline comment.shortText}}}{{/if}}\n                {{/each}}\n            {{/if}}\n\n            {{{comment.shortText}}}\n            {{#if comment.text}}\n\n            {{{comment.text}}}\n            {{/if}}\n\n        {{/each}}\n    {{/each}}\n\n    {{#if props}}\n    ## Properties and Accessors\n \n    | Name | Type | Description\n    |--- |--- |---\n    {{#each props}}\n    | {{name}} | {{#if type.id}}[{{type.name}}](#{{type.name}}){{else}}{{type.name}}{{/if}}{{#if type.typeArguments}}&lt;{{type.typeArguments.[0].name}}&gt;{{/if}}{{#if getSignature}}{{getSignature.type.name}}{{/if}} | {{#if comment.text}}{{{no-newline comment.text}}}{{else}}{{{no-newline comment.shortText}}}{{/if}}\n    {{/each}}\n    {{/if}}\n\n    {{#if methods.length}}\n        ## {{name}} Class Methods\n        {{#each methods}}\n            <a name=\"{{name}}\"></a>\n            ### {{name}}()\n            {{#each signatures}}\n                {{{comment.shortText}}}\n                {{#if parameters}}\n\n                    **Parameters**\n\n                    | Argument | Type | description\n                    |--- |--- |---\n                    {{#each parameters}}\n                    | {{name}}{{#if flags.isOptional}} (optional){{/if}}| {{#if type.id}}[{{type.name}}](#{{type.name}}){{else}}{{type.name}}{{/if}}{{#if type.typeArguments}}&lt;{{type.typeArguments.[0].name}}&gt;{{/if}} | {{#if comment.shortText}}{{{no-newline comment.shortText}}}<br/>{{/if}}{{#if comment.text}}{{{no-newline comment.text}}}{{/if}}\n                    {{/each}}\n\n                {{/if}}\n                {{#if comment.returns}}\n                \n                **Returns**\n\n                {{comment.returns}}\n\n                {{/if}}\n\n                {{#if comment.text}}\n\n                {{{comment.text}}}\n                {{/if}}\n            {{/each}}\n\n        {{/each}}\n    {{/if}}\n\n{{/if}}\n{{/each}}\n\n{{#each interfaces}}\n{{#if flags.isExported}}\n<a name=\"{{name}}\"></a>\n## Interface {{name}}\n{{{comment.shortText}}}\n{{#if comment.text}}\n\n{{{comment.text}}}\n{{/if}}\n\n    {{#if props}}\n    **Fields**\n\n    | Name | Type | Description\n    |--- |--- |---\n    {{#each props}}\n    | {{name}} | {{#if type.id}}[{{type.name}}](#{{type.name}}){{else}}{{type.name}}{{/if}}{{#if type.typeArguments}}&lt;{{type.typeArguments.[0].name}}&gt;{{/if}} | {{#if comment.shortText}}{{{no-newline comment.shortText}}}<br/>{{/if}}{{#if comment.text}}{{{no-newline comment.text}}}{{/if}}\n    {{/each}}\n    {{/if}}\n{{/if}}\n{{/each}}\n"
  },
  {
    "path": "packages/docs/build/toc-platforms.hbs",
    "content": "# {{title}}\n\n[&larr; Botkit Core Docs](../core.md)\n\n{{#each index}}\n* [{{name}}](../{{path}})\n    {{#each classes}}\n    * [{{name}}](../{{../path}}#{{name}})\n    {{/each}}\n{{/each}}\n* [Microsoft Teams](../core.md#using-bot-framework-channels)\n"
  },
  {
    "path": "packages/docs/build/toc.hbs",
    "content": "# {{title}}\n\n[&larr; Botkit Core Docs](../core.md)\n\n{{#each index}}\n* [{{name}}](../{{path}})\n    {{#each classes}}\n    * [{{name}}](../{{../path}}#{{name}})\n    {{/each}}\n{{/each}}"
  },
  {
    "path": "packages/docs/conversations.md",
    "content": "# Botkit Conversations\n\nBotkit's core SDK ships with a Botkit-friendly dialog class called [BotkitConversation](reference/core.md#botkitconversation). This class offers developers a familiar syntax for creating scripted dialogs,\nand injecting dynamic behaviors. \n\nDialogs are created using functions like [convo.ask()](reference/core.md#ask) and [convo.say()](reference/core.md#say-1), and dynamic actions can be implemented using a hook system ([convo.before()](reference/core.md#before), [convo.after()](reference/core.md#after) and [convo.onChange()](reference/core.md#onchange)) that provides conversation context and a `bot` worker object at key points in the dialog's execution.\n\n## Import the class\n\nTo use BotkitConversations, make sure to import the class along with Botkit:\n\n```javascript\nconst { Botkit, BotkitConversation } = require('botkit');\n```\n\n## Anatomy of a Botkit Conversation\n\nThe `BotkitConversation` class is an implementation of the [BotBuilder Dialog base class](https://npmjs.com/package/botbuilder-dialogs) that provides a fluent interface for defining the structure and content of an interactive dialog. \n\nBotkitConversations are constructed from one or more sequences of messages known as \"[threads](#conversation-threads).\" The threads can be linked to one another, and conditional branches and loops can be created. Each item in a thread is a message template - they can include variable tokens that will be replaced with live values automatically before being sent. [Read about constructing a dialog here &rarr;](#build-a-conversation)\n\nAll dialogs must be defined and added to the Botkit controller _at start time._ It is bad practice to create new dialogs from within handler functions or in response to user actions - this may cause your bot to lose its place in the conversation, or become confused. Think about it this way: your bot has to know every possible dialog and action it might take at start time so that it can consistently respond across multiple instances of the application, or between restarts.\n\nLike all conversations, those conducted by your bot have a beginning, middle and an end. Botkit provides ways to hook into all of these events to make your dialog more dynamic and useful:\n\n### Beginning\n\nBotkitConversations start on the first message of the \"default\" thread, and proceed through the chain of messages.\n\nHowever, before it starts sending messages, Botkit will first fire any functions bound to the \"default\" thread using the [before()](reference/core.md#before) hook. These functions can create or change variables, and take other necessary actions - for example, looking up values in a database or external API for use in the conversation.\n\nThe bot will continue to process messages in the thread until it reaches a prompt, an action, or the end of the thread.\n\n### Middle\n\nAs each message is read from the dialog script and sent to the user, it is evaluated for template variables. Variables may be used in almost any field in the message object. [Learn more about using variables &rarr;](#using-variable-tokens-and-templates-in-conversation-threads)\n\nWhen a prompt is encountered, the message will first be sent to the user. The bot will then wait for the next message to arrive.  When it does, the value of the incoming message will automatically be captured into a variable, and any [onChange()](reference/core.md#onchange) functions that have been bound to that variable will fire. These handler functions can be used to validate the incoming value, or take other conditional actions based on the user input.\n\nAfter `onChange` hooks fire, Botkit will proceed to evaluate the handler function or conditional tests that were passed in to `ask()` or `addQuestion()`. These functions may set variables, or modify the flow of the dialog by calling [repeat()](reference/core.md#repeat) or [gotoThread()](reference/core.md#gotothread).\n\nHook functions can be bound to the beginning of _each thread_ using [before()](reference/core.md#before). Each thread will fire it's own `before` hooks _before_ sending the first message. This can be used for a variety of purposes, including conditionally skipping a thread (by calling `gotoThread()` from inside a `before()` hook).\n\n### End\n\nWhen the dialog reaches its end (no messages remaining to be sent, or one of the end actions called), it will fire its last set of hooks, and then finally come to an end.  The end of a conversation can be thought of in the same light as a web form \"submit\" -- all of the user responses and any other information collected during the course of the conversation will be sent to the final hook for processing.  Commonly, these hooks are used to store/submit that information, and then possibly to begin the next dialog.\n\nThere are several ways to register an end-of-conversation hook, [discussed in more detail here &rarr;](#handling-end-of-conversation)\n\n## Build a Conversation\n\nFirst, create the new dialog object. Each dialog must have it's own unique identifier that will be used to invoke it later:\n\n```javascript\nconst MY_DIALOG_ID = 'my-dialog-name-constant';\nlet convo = new BotkitConversation(MY_DIALOG_ID, controller);\n```\n\nThen, using the helper methods like `say()` and `ask()`, define a series of messages, questions and actions that will be taken:\n\n| Method | Description\n|--- |---\n| [say()](reference/core.md#say-1) | Add a normal message template to the default thread\n| [ask()](reference/core.md#ask) | Add a questin/prompt to the default thread\n| [addMessage()](reference/core.md#addmessage) | Add a message template to a thread\n| [addQuestion()](reference/core.md#addquestion) | Add a question/prompt to a thread\n| [addAction()](reference/core.md#addaction) | Add an action (or instructions to switch threads) to a thread\n| [addChildDialog()](reference/core.md#addchilddialog) |  Add a child-dialog to a thread\n| [addGotoDialog()](reference/core.md#addgotodialog) | Add instructions to jump to another dialog\n\n```javascript\n// send a greeting\nconvo.say('Howdy!');\n\n// ask a question, store the response in 'name'\nconvo.ask('What is your name?', async(response, convo, bot) => {\n    console.log(`user name is ${ response }`);\n    // do something?\n}, 'name');\n\n// use add action to switch to a different thread, defined below...\nconvo.addAction('favorite_color');\n\n// add a message and a prompt to a new thread called `favorite_color`\nconvo.addMessage('Awesome {{vars.name}}!', 'favorite_color');\nconvo.addQuestion('Now, what is your favorite color?', async(response, convo, bot) => {\n    console.log(`user favorite color is ${ response }`);\n},'color', 'favorite_color');\n\n// go to a confirmation\nconvo.addAction('confirmation' ,'favorite_color');\n\n// do a simple conditional branch looking for user to say \"no\"\nconvo.addQuestion('Your name is {{vars.name}} and your favorite color is {{vars.color}}. Is that right?', [\n    {\n        pattern: 'no',\n        handler: async(response, convo, bot) => {\n            // if user says no, go back to favorite color.\n            await convo.gotoThread('favorite_color');\n        }\n    },\n    {\n        default: true,\n        handler: async(response, convo, bot) => {\n            // do nothing, allow convo to complete.\n        }\n    }\n], 'confirm', 'confirmation');\n```\n\nFinally, make sure to add the dialog to the Botkit controller. This activates the dialog and makes it available to use later:\n\n```javascript\ncontroller.addDialog(convo);\n```\n\n## Trigger Conversations\n\n* [beginDialog()](reference/core.md#beginDialog)\n* [addChildDialog()](reference/core.md#addchilddialog)\n* [addGotoDialog()](reference/core.md#addgotodialog)\n\n## Hooks\n\n* [before()](reference/core.md#before)\n* [onChange()](reference/core.md#onchange)\n* [after()](reference/core.md#after)\n\n## Conversation Threads\n\nComplex conversations that require branching, repeating or looping sections of dialog,\nor data validation can be handled using feature of the conversations we call `threads`.\n\nThreads are pre-built chains of dialog between the bot and end user that are built before the conversation begins. Once threads are built, Botkit can be instructed to navigate through the threads automatically, allowing many common programming scenarios such as yes/no/quit prompts to be handled without additional code.\n\nYou can build conversation threads in code, or you can use [Botkit CMS](https://github.com/howdyai/botkit-cms)'s script management tool to build them in a friendly web environment and then import them dynamically to the application with [botkit-plugin-cms](plugins/cms.md). Conversations you build yourself and conversations managed in Botkit CMS work the same way -- they run inside your bot and use your code to manage the outcome.\n\nIf you've used the conversation system at all, you've used threads - you just didn't know it. When calling `convo.say()` and `convo.ask()`, you were actually adding messages to the `default` conversation thread that is activated when the conversation object is created.\n\n## Automatically Switch Threads using Actions\n\nYou can direct a conversation to switch from one thread to another by using [addAction()](reference/core.md#addaction), or\nby including the `action` field on a message object. Botkit will switch threads immediately after sending the message.\n\n```javascript\n// first, define a thread called `next_step` that we'll route to...\nconvo.addMessage({\n    text: 'This is the next step...',\n},'next_step');\n\n\n// send a message, and tell botkit to immediately go to the next_step thread\nconvo.addMessage({\n    text: 'Anyways, moving on...',\n    action: 'next_step',\n});\n```\n\nDevelopers can create complex conversational systems by combining these message actions with conditionals in `ask()` and `addQuestion()`. Actions can be used to specify default or next step actions, while conditionals can be used to route between threads.\n\nFrom inside a prompt handler function, use `convo.gotoThread()` to instantly switch to a different part of the conversation. Botkit can be set to automatically navigate between threads based on user input, such as in the example below.\n\n```javascript\n    let convo = new BotkitConversation('cheese', controller);\n\n    // create a path for when a user says YES\n    convo.addMessage({\n            text: 'You said yes! How wonderful.',\n    },'yes_thread');\n\n    // create a path for when a user says NO\n    convo.addMessage({\n        text: 'You said no, that is too bad.',\n    },'no_thread');\n\n    // create a path where neither option was matched\n    // this message has an action field, which directs botkit to go back to the `default` thread after sending this message.\n    convo.addMessage({\n        text: 'Sorry I did not understand.',\n        action: 'default',\n    },'bad_response');\n\n    // Create a yes/no question in the default thread...\n    convo.addQuestion('Do you like cheese?', [\n        {\n            pattern: 'yes',\n            handler: async function(response, convo, bot) {\n                await convo.gotoThread('yes_thread');\n            },\n        },\n        {\n            pattern: 'no',\n            handler: async function(response, convo, bot) {\n                await convo.gotoThread('no_thread');\n            },\n        },\n        {\n            default: true,\n            handler: async function(response, convo, bot) {\n                await convo.gotoThread('bad_response');\n            },\n        }\n    ],'likes_cheese','default');\n\n    controller.addDialog(convo);\n});\n```\n\n## Special Actions\n\nIn addition to routing from one thread to another using actions, you can also use\none of a few reserved words to control the conversation flow.\n\nSet the action field of a message to `complete` to end the conversation immediately and mark as success.\n\nSet the action field of a message to `stop` end immediately, but mark as failed.\n\nSet the action field of a message to `timeout` to end immediately and indicate that the conversation has timed out.\n\nAfter the conversation ends, these values will be available in the `_status` field of the results parameter. This field can then be used to check the final outcome of a conversation. See [handling the end of conversations](#handling-end-of-conversation).\n\n## Using Variable Tokens and Templates in Conversation Threads\n\nPre-defined conversation threads are great, but many times developers will need to inject dynamic content into a conversation.\nBotkit achieves this by processing the text of every message using the [Mustache template language](https://mustache.github.io/).\nMustache offers token replacement, as well as access to basic iterators and conditionals.\n\nVariables can be added to a conversation at any point after the conversation object has been created using the function `convo.setVar()`. See the example below.\n\n```javascript\n    // .. define threads which will use variables...\n    // .. and then, set variable values:\n    convo.setVar('foo','bar');\n    convo.setVar('list',[{value:'option 1'},{value:'option 2'}]);\n    convo.setVar('object',{'name': 'Chester', 'type': 'imaginary'});\n});\n```\n\nGiven the variables defined in this code sample, `foo`, a simple string, `list`, an array, and `object`, a JSON-style object,\nthe following Mustache tokens and patterns would be available:\n\n```\nThe value of foo is {{vars.foo}}\n\nThe items in this list include {{#vars.list}}{{value}}{{/vars.list}}\n\nThe object's name is {{vars.object.name}}.\n```\n\nBotkit ensures that your template is a valid Mustache template, and passes the variables you specify directly to the Mustache template rendering system.\nOur philosophy is that it is OK to stuff whatever type of information your conversation needs into these variables and use them as you please!\n\n## Dynamic Text, Quick Replies and Attachments\n\nIn some cases, developers will need to create dynamic quick replies and/or attachments to the messages within an otherwise pre-scripted dialog.\nAs of Botkit v4.5, this can be achieved by specifying a function responsible for generating this content as part of the message template.\n\nFunctions may be passed in in the `text`, `quick_replies`, `attachment`, `attachments` and `blocks` fields.  All of these functions share the same signature:\n`async(message_template, vars) => { return CONTENT; }`\n\nThe `message_template` parameter includes the entire template initially passed in to `ask()` or `say()` or any other function used to construct the dialog structure.\n\nThe `vars` parameter includes all of the currently available conversation variables otherwise accessible via `convo.vars` and/or the `{{vars.name}}` syntax.\n\nThese two variables, along with any other information currently in scope, can be used to dynamically generate these attachments, as seen in the example below:\n\n```\nlet dialog = new BotkitConversation('sample_dialog', controller);\n\ndialog.ask('What would you like the quick reply to say?', [], 'reply_title');\ndialog.say({\n    text: 'Here is your dynamic button:',\n    quick_replies: async(template, vars) => { return [{title: vars.reply_title, payload: vars.reply_title }]}\n});\n```\n\nThese generator functions are responsible for creating the attachment content in the platform-appropriate format.  The returned content may include `{{vars.name}}` style Mustache tags.\n\n## Conversation Control Functions\n\nWhen a user responds to a prompt, the answer is automatically added to the list of variables.\nThen, any conditionals or handler functions associated with the prompt will be fired.\n\nAll the conditions will be tested in the order they are specified in code. If no other condition matches, Botkit will fire the handler that includes `default: true`.\nFor the winning condition, the handler function will fire. The handler receives 3 parameters: the raw response to the prompt, a [convo helper object](reference/core.md#botkitdialogwrapper), \nand a [bot worker](reference/core.md#botworker).\n\nSeveral helper functions are available in order to direct the flow of the conversation from within the handler:\n\n* [convo.repeat()](reference/core.md#repeat)\n* [convo.setVar()](reference/core.md#setvar)\n* [convo.gotoThread()](reference/core.md#gotothread)\n\n## Composing Dialogs\n\nMultiple dialogs can be combined into larger, more complex interactions. The results of \"child\" dialogs roll up to the \"parent\" dialog.\n\nTo use a child dialog, add a pointer to it to the parent dialog using [addChildDialog()](reference/core.md#addchilddialog). Then, at the appropriate place in the performance of the parent dialog, the bot will switch automatically to the child dialog, run it to completion, then resume the parent dialog where it left off. The results of the child dialog (any variables or user responses captured) will be stored in the parent dialog's variable set.\n\n```javascript\nlet parent = new BotkitConversation(PARENT_ID, controller);\nlet child = new BotkitConversation(CHILD_ID, controller);\n\nparent.say('I have a few questions...');\nparent.addChildDialog(CHILD_ID, 'answers'); // capture responses in vars.questions\n\nchild.ask('Question 1!',[], 'question_1'); // no handler\nchild.ask('Question 2!',[], 'question_2'); // no handler\nchild.ask('Question 3!',[], 'question_3'); // no handler\n\ncontroller.addDialog(parent);\ncontroller.addDialog(child);\ncontroller.afterDialog(parent, async(bot, results) => {\n\n    let question_1 = results.answers.question_1;\n    let question_2 = results.answers.question_2;\n    // ... do stuff with responses\n\n});\n```\n\n## Handling End of Conversation\n\nAny dialog - not just `BotkitConversations`, but any [dialog built on the BotBuilder dialog base class](https://npmjs.com/package/botbuilder-dialogs) - will emit a special event whenever it completes that can be handled using [afterDialog()](reference/core.md#afterdialog). Each handler function will receive an object containing all of the variables set and/or collected during the course of the conversation, and a [bot worker](reference/core.md#botworker) object that can take further actions.\n\nConversations end naturally when the last message has been sent and no messages remain in the queue.\nIn this case, the value of `results._status` will be `completed`. Other values for this field include `canceled`, and `timeout`.\n\n```javascript\nconst my_dialog = new BotkitDialog('dialog', controller);\nmy_dialog.ask('What is your name?', [], 'name');\ncontroller.addDialog(my_dialog);\n\ncontroller.afterDialog(my_dialog, async(bot, results) => {\n\n    // use results of dialog here\n    let name = results.name;\n\n    // do some cool database stuff here\n\n    // start next dialog\n    await bot.beginDialog(NEXT_DIALOG);\n\n});\n```\n\nWhen constructing `BotkitConversation` dialogs, it may be easier to define the end-of-conversation handler directly on the dialog object using [after()](reference/core.md#after).  This is an equivalent method of binding the handler, though the order of the parameters _is reversed here_ with the first parameter being containing the dialog results instead of the second.\n\nNote that this syntax is only supported by BotkitConversation, so it when using a mix of dialog types, it may be better to standardize on the `afterDialog()` syntax.\n\n```javascript\nconvo.after(async(results, bot) => {\n    // TODO\n    if (results._status === 'completed') {\n        // any variable set with convo.setVar\n        // and any response to convo.ask or convo.addQuestion\n        // is present as results[keyname]\n\n        // can do things like\n        // await bot.beginDialog(NEXT_DIALOG);\n    }\n});\n```\n"
  },
  {
    "path": "packages/docs/core.md",
    "content": "# Botkit Core \n\nTable of Contents\n\n* [The Botkit Controller](#the-botkit-controller)\n* [Botkit Basics](#botkit-basics)\n* [Receiving Messages](#receiving-messages-and-events)\n* [Sending Messages](#sending-messages)\n* [Using Dialogs](#using-dialogs)\n* [Organize Your Bot Code](#organize-your-bot-code)\n* [Using Bot Framework Channels](#using-bot-framework-channels)\n* [Building & Using Plugins](#building--using-plugins)\n* [Middlewares](#middlewares)\n\n## The Botkit Controller\n\nThe robot brain inside every Botkit applications is the `controller`, an interface that is used to define all the features and functionality of an app. Botkit's core library provides a platform-independent interface for sending and receiving messages so that bots on any platform can be created using the same set of tools.\n\nBy attaching event handlers to the controller object, developers can specify what type of messages and events their bot should look for and respond to, including keywords, patterns and status events. These event handlers can be thought of metaphorically as skills or features the robot brain has -- each event handler defines a new \"When a human says THIS the bot does THAT.\"\n\nOnce created, the controller will handle incoming messages, [spawn bot instances](reference/core.md#spawn) and [trigger handlers](#receiving-messages-and-events).\n\nFor each platform, there is a specialized version of the controller object. These specialized controllers customize Botkit's core features to work with the platform, and add additional features above and beyond core that offer developers access platform-specific features.\n\nBotkit can connect to multiple messaging channels through the [Microsoft Bot Framework Service](https://dev.botframework.com).\nNo plugins are necessary to use the Bot Framework service, and bots can be developed locally using the [Bot Framework Emulator](https://aka.ms/botemulator). [Read more about using the Bot Framework](#using-bot-framework-channels).\n\nThe Botkit project includes several official adapters. Using these plugins, your bot can communicate directly with the messaging platforms. Each platform has its own set of configuration options - refer to the platform connector docs for details:\n\n* [Web and Apps](platforms/web.md)\n* [Slack](platforms/slack.md)\n* [Webex Teams](platforms/webex.md)\n* [Google Hangouts](platforms/hangouts.md)\n* [Facebook Messenger](platforms/facebook.md)\n* [Twilio SMS](platforms/twilio-sms.md)\n* [Microsoft Teams](#ms-teams-extensions)\n\nIn addition, the open source community has created a variety of plugins and extensions to Bot Framework.  Check out the [Bot Builder Community Repo](https://github.com/BotBuilderCommunity/botbuilder-community-js) for additional adapters, storage connectors and middlewares.\n\n## Botkit Basics\n\nIn this simple example below, Botkit creates a webhook endpoint for communicating with the [Bot Framework Emulator](https://aka.ms/botemulator), and is configured with a single \"hears\" handler that instructs Botkit to listen for a wildcard pattern, and to respond to any incoming message.\n\n```javascript\nconst { Botkit } = require('botkit');\n\nconst controller = new Botkit({\n    webhook_uri: '/api/messages',\n});\n\ncontroller.hears('.*','message', async(bot, message) => {\n\n    await bot.reply(message, 'I heard: ' + message.text);\n\n});\n\ncontroller.on('event', async(bot, message) => {\n    await bot.reply(message,'I received an event of type ' + message.type);\n});\n```\n\n## Receiving Messages and Events\n\nOnce connected to a messaging platform, bots receive a constant stream of events - everything from the normal messages you would expect to typing notifications and presence change events. The set of events your bot will receive will depend on what messaging platform it is connected to.\n\nTo respond to events, use [controller.on()](reference/core.md#on) to define a handler function that receives the event details and takes actions.\n\nIncoming events will be in [this format](reference/core.md#botkitmessage).\n\nNote that Botkit leaves all the native fields intact, so any fields that come in from the platform are still present in the object.\nHowever, our recommendation for accessing any platform-native fields is to use the `message.incoming_message` field\nwhich contains an unmodified version of the [BotBuilder Activity](https://docs.microsoft.com/en-us/javascript/api/botframework-schema/activity?view=botbuilder-ts-latest), or reach even further into `message.incoming_message.channelData` which contains an unmodified copy of the raw source webhook payload.\n\n### Matching Patterns and Keywords with `hears()`\n\nIn addition to traditional event handlers, Botkit also provides the [controller.hears()](reference/core.md#hears) function, which configures event handlers that look for specific keywords or phrases in the message.\n\nEach call to `controller.hears()` sets up a separate set of patterns to listen for.\nDevelopers may specify a single pattern to match, or an array of patterns.\nBy default, Botkit treats these patterns as regular expressions to be evaluated against the `message.text` field in incoming messages.\n\nIn addition to the array of patterns, `hears()` also receives as an argument one or more event types.\nOnly events of the type listed will be evaluated.\n\nIt is important to note that Botkit will *stop processing handlers* when the first `hears()` trigger is matched.\nTriggers are evaluated in the order in which they are defined in the code.\nThis is a major difference in the way most event handling systems work, which will fire all matching handlers, and differs from handlers\nconfigured with [controller.on()](reference/core.md#on), which behave as expected.\n\n```javascript\ncontroller.hears(['hi','hello','howdy','hey','aloha','hola','bonjour','oi'],['message'], async (bot,message) => {\n\n  // do something to respond to message\n  await bot.reply(message,'Oh hai!');\n\n});\n```\n\n### Interruptions\n\nSome bots have certain operations that should take precidence, even if that means stopping or interupting an ongoing conversation. Near universal examples of this are providing a \"help\" command, and providing a \"quit\" mechanism.\n\nFor this type of trigger, Botkit provides a version of \"hearing\" that occurs _before_ any other processing of the message: [interrupts()](reference/core.md#interrupts). Botkit will look for interruptions before passing the message through the dialog system, and before looking for any other triggers. `interrupts()` works just like `hears()` - it takes the same parameters, and functions the same way: if a trigger is matched, further processing of the message is halted.\n\n[Learn more about ways to combine multiple dialogs into bigger experiences](conversations.md#composing-dialogs)\n\n\n```javascript\ncontroller.interrupts('help', 'message', async(bot, message) => {\n    // start a help dialog, then eventually resume any ongoing dialog\n    await bot.beginDialog(HELP_DIALOG);\n});\n\ncontroller.interrupts('quit', 'message', async(bot, message) => {\n    await bot.reply(message, 'Quitting!');\n\n    // cancel any active dialogs\n    await bot.cancelAllDialogs();\n});\n```\n\n### Matching regular expressions\n\nIn addition to simple keyword matches, `hears()` can also accept one or more [regular expressions](https://regex101.com/) that will match against the `message.text` with more control. \n\nWhen using regular expressions, any capture groups will resulting from the test can be found in `message.matches`.\n\n```javascript\ncontroller.hears(new RegExp(/^reboot (.*?)$/i), 'message', async(bot, message) => {\n\n    // message.matches is the result of message.text.match(regexp) so in this case the parameter is in message.matches[1]\n    let param = message.matches[1];\n    await bot.reply(message, `I will reboot ${ param }`);\n\n});\n```\n\n### Matching with a function\n\nFor more sophisticated matches, `hears()` can also accept one or more test functions.  These test functions must be in the form:\n\n```javascript\nasync (message) => {\n    // some test\n    if (some_test) {\n        return true;\n    } else {\n        return false;\n    }\n}\n```\n\nUsing async functions to match triggers allows nearly limitless mechanisms to be put in play to evaluate a message. Functions can be used to test fields other than `message.text,` for example, or can test for fields added by middleware plugins such as possible `intents` added by an NLP middleware.\n\nHere are a few examples:\n```javascript\n// \"listen\" for the message.intent field to be set to \"help\"\ncontroller.hears(async(message) => { return message.intent===\"help\" }, 'message', async(bot, message) => { \n    // do something\n});\n\n// listen for extremely long messages\ncontroller.hears(async(message) => { return (message.text.length > 100) }, 'message', async(bot, message) => { \n    // do something\n});\n\n// compare a value in the message against a database\n// (only hear a message if user is already in the database)\ncontroller.hears(async(message) => {\n    return new Promise((resolve, reject) => {\n        myDatabase.get(message.user).then(function(user) {\n            if (user) {\n                resolve(true);\n            } else {\n                resolve(false);\n            }\n        }).catch(reject);\n    });\n},  'message', async(bot, message) => {\n    // handle trigger\n});\n\n// listen for a facebook sticker\ncontroller.hears(async(message) => { return message.sticker_id; }, 'message', async(bot, message) => {\n    await bot.reply(message,'cool sticker.');\n});\n```\n\n## Sending Messages\n\nSending messages is a bots primary way of communicating with users and presenting its interface to the world.\nThere are three primary scenarios in which bots send messages:\n\n* [Sending replies to incoming messages](#replying-to-incoming-messages)\n* [Sending alerts and scheduled messages](#sending-alerts-and-scheduled-messages)\n* [Conducting multi-message dialog scripts](#using-dialogs)\n\n## Replying to Incoming Messages\n\nOnce a bot has received a message using a [controller.on()](reference/core.md#on) or [controller.hears()](reference/core.md#hears) event handler, a response can be sent using [bot.reply()](reference/core.md#reply).\n\nMessages sent using `bot.reply()` are sent immediately. If multiple messages are sent via\n`bot.reply()` in a single event handler, they will arrive one after another with no delay.\n\nA simple echo response:\n```javascript\ncontroller.on('message', async(bot, message) => {\n    await bot.reply(message, 'I heard you say something!');\n});\n```\n\nReply messages can contain additional fields - what features are available depends on the messaging platform in use.\nBotkit will automatically map message fields to the appropriate, platform-specific location.\n\n```javascript\ncontroller.on('message', async(bot, message) => { \n\n    await bot.reply(message, {\n        text: 'Here is a menu!',\n        quick_replies: [\n            {\n                title: \"Main\",\n                payload: \"main-menu\",\n            },\n            {\n                title: \"Help\",\n                payload: \"help\"\n            }\n        ]\n    });\n});\n```\n\n## Sending alerts and scheduled messages\n\nThere are some cases when a bot will send a message to a user that is not in direct response to an incoming message.\n\n* In response to an external event such as a webhook from a third party integration\n* Based on a cronjob or some other scheduling mechanism\n* Sending timed or scheduled broadcast messages\n\nTo do this requires a few pieces of information - credentials necessary to make API calls, and a complicated set of fields that comprise a \"conversation reference\" that points to a specific user in a specific channel on a specific platform. Botkit provides a few helper functions that make this a bit easier to manage.\n\nTo send this type of \"proactive\" message, you must first [spawn](reference/core.md#spawn) a [bot](reference/core.md#botworker), then give it a context (usually a user id, or a user id + channel) for it to do stuff like send messages and [start dialogs](#using-dialogs).\n\nIt looks _something_ like the code below, though it should be noted that there are variations in how `controller.spawn()` works from platform to platform -- notably [Slack](reference/slack.md#create-a-new-slackbotworker) and [Facebook](reference/facebook.md#create-a-new-facebookbotworker) -- and also some variation in the availability of helper functions like `startConversationWithUser()` used below.  Check [platform docs](platforms/index.md) for these details!\n\n```javascript\nasync (trigger) => {\n\n    // there's a user id somewhere in this trigger\n    let user = trigger.userid;\n\n    // spawn a bot\n    let bot = await controller.spawn();\n\n    await bot.startConversationWithUser(user);\n\n    await bot.say('ALERT! A trigger was detected');\n    await bot.beginDialog(ALERT_DIALOG);\n\n}\n```\n\n### Capture a reference from an incoming message\n\nEach incoming message received by Botkit contains a conversation reference in the `message.reference` field.\nCapture this reference value and store it for later use with [bot.changeContext()](reference/core.md#changecontext) \nto continue sending messages _in that same context_.\n\nImagine a bot that, hearing the keyword \"subscribe\" captures the reference for use to later send a push notification:\n\n```javascript\ncontroller.hears('subscribe', 'message', async(bot, message) => {\n\n    let reference = message.reference;\n    let user = message.user;\n\n    // store reference associated with user\n    await mydatabase.subscribeUser(user, reference);\n\n    await bot.reply(message, 'You are subscribed to alerts in this channel.');\n\n});\n```\n\nLater, an alert is to be generated for the user based on an trigger of some sort:\n```javascript\nasync(trigger) => {\n\n    let user = trigger.userid;\n    let reference = mydatabase.getSubscription(user);\n    \n    let bot = await controller.spawn();\n    await bot.changeContext(reference);\n\n    await bot.say('Breaking news!');\n\n}\n```\n\n### Use a platform-specific `startConversation*` method\n\nMost of the platform adapters provide convenience methods that can use used to begin or resume a conversation with a user based on their user id, as well as other relevant factors such as channel id. These can be used in lieu of capturing a pre-existing reference from an incoming message.\n\n* [Slack](platforms/slack.md#start-or-resume-conversations-with-people)\n* [Facebook](reference/facebook.md#startconversationwithuser)\n* [Webex Teams](reference/webex.md#startconversationinroom)\n* [Twilio SMS](reference/twilio-sms.md#startconversationwithuser)\n* [Google Hangouts](reference/hangouts.md#startconversationinthread)\n\n\n## Using Dialogs\n\nBotkit's multi-turn conversation system is built on top of [BotBuilder's dialog system](https://www.npmjs.com/package/botbuilder-dialogs) that provides many built-in niceties like [conversation state persistence](#enable-conversation-persistence), [typed prompts with validators](https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-concept-dialog?view=azure-bot-service-4.0#prompts), and other advanced features. All of these features may now be used alongside Botkit!\n\nDialogs contain pre-defined \"maps\" for conversations that can be triggered in various ways. Think of a dialog as a the script for an interactive, potentially branching conversation the bot can conduct. Dialogs can contain conditional tests, branching patterns, and dynamic content. There are a variety of ways to create dialogs, including one that [uses Botkit's familar syntax](conversations.md), as well as BotBuilder's own [WaterfallDialogs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-dialogs/waterfalldialog?view=botbuilder-ts-latest).\n\nIn order to use a dialog, it must first be defined and added to the bot's dialog stack. Below is an example showing the use of the `BotkitConversation` dialog type.\n\n```javascript\n// Import the BotkitConversation dialog class\nconst { BotkitConversation } = require('botkit');\n\n// Create a very simple dialog with 2 messages.\nlet DIALOG_ID = 'my_dialog_1';\nlet myDialog = new BotkitConversation(DIALOG_ID, controller);\nmyDialog.say('Hello!');\nmyDialog.say('Welcome to the world of bots!');\n\n// Add the dialog to the bot\ncontroller.addDialog(myDialog);\n\n// Later, trigger the dialog\ncontroller.on('channel_join', async(bot, message) => {\n    await bot.beginDialog(DIALOG_ID);\n});\n```\n\nDialog objects, once defined, are added to the bot using [controller.addDialog()](reference/core.md#adddialog) and\nthen triggered with [bot.beginDialog()](reference/core.md#begindialog).\n\n### Botkit Conversations\n\n[BotkitConversation](reference/core.md#botkitconversation) provides an interface for creating dialogs that is based on the\noriginal Botkit \"convo\" syntax: Dialogs are created using functions like [convo.ask()](reference/cms.md#ask) and [convo.say()](reference/cms.md#say), and dynamic actions can be implemented using a hook system ([convo.before()](reference/cms.md#before), [convo.after()](reference/cms.md#after) and [convo.onChange()](reference/cms.md#onchange)) that provides conversation context and a `bot` worker object at key points in the dialog's execution.\n\n[Read all about Botkit Conversations &rarr;](conversations.md)\n\nA simple example:\n```javascript\nconst { BotkitConversation } = require('botkit');\n\n// define the conversation\nconst onboarding = new BotkitConversation('onboarding', controller);\n\nonboarding.say('Hello human!');\n// collect a value with no conditions\nonboarding.ask('What is your name?', async(answer) => { \n    // do nothing.\n}, {key: 'name'});\n\n// collect a value with conditional actions\nonboarding.ask('Do you like tacos?', [\n    {\n        pattern: 'yes',\n        handler: async function(answer, convo, bot) {\n            await convo.gotoThread('likes_tacos');\n        }\n    },\n    {\n        pattern: 'no',\n        handler: async function(answer, convo, bot) {\n            await convo.gotoThread('hates_life');\n        }\n    }\n],{key: 'tacos'});\n\n// define a 'likes_tacos' thread\nonboarding.addMessage('HOORAY TACOS', 'likes_tacos');\n\n// define a 'hates_life' thread\nonboarding.addMessage('TOO BAD!', 'hates_life');\n\n// handle the end of the conversation\nonboarding.after(async(results, bot) => {\n    const name = results.name;\n});\n\n// add the conversation to the dialogset\ncontroller.addDialog(onboarding);\n\n// launch the dialog in response to a message or event\ncontroller.hears(['hello'], 'message', async(bot, message) => {\n    bot.beginDialog('onboarding');\n});\n```\n\n\n### Botkit CMS\n\n[Botkit CMS](https://github.com/howdyai/botkit-cms) is an external content management system for dialogs systems. Botkit can automatically attach to a CMS instance and import content into [BotkitConversation](reference/core.md#botkitconversation) objects automatically.\n\nIn order to enable this functionality, add the [botkit-plugin-cms](plugins/cms.md) plugin to your application, and\nload it into your Botkit controller at bootup using [controller.usePlugin()](reference/core.md#useplugin) as seen below:\n\n```javascript\nconst { BotkitCMSHelper } = require('botkit-plugin-cms');\n\nconst controller = new Botkit(OPTIONS);\ncontroller.usePlugin(new BotkitCMSHelper({\n    uri: process.env.CMS_URI,\n    token: process.env.CMS_TOKEN\n}));\n```\n\nLoading the plugin this way will extend the controller with new object at `controller.plugins.cms` with [these helpful methods](reference/cms.md#botkitcmshelper-class-methods).\n\nTo use the Botkit CMS trigger API to automatically evaluate messages and fire the appropriate dialog, use `controller.plugins.cms.testTrigger()` as below:\n\n```javascript\ncontroller.on('message', async (bot, message) => {\n    let results = await controller.plugins.cms.testTrigger(bot, message);\n});\n```\n\nDevelopers may hook into the dialogs as they execute using \n[controller.plugins.cms.before()](reference/cms.md#before),\n[controller.plugins.cms.after()](reference/cms.md#after),\nand [controller.plugins.cms.onChange()](reference/cms.md#onchange).\nThese methods operate identically to the [BotkitConversation analogs of these methods](reference/core.md#botkitconversation-class-methods), but take an additional parameter of the dialog's _name_, allowing handlers to be bound to the externally loaded content.\n\nNOTE: Before handlers can be bound to a dialog, it must exist in the dialogSet.  To make sure this has happened, place any handler definitions inside a call to `controller.ready()`, which will fire only after all dependent subsystems have fully booted.\n\n```javascript\ncontroller.ready(() => {    \n    // fire a function before the `default` thread begins\n    // and set a variable available to the template system\n    controller.plugins.cms.before('onboarding','default', async (bot, convo) => {\n        convo.vars.foo = 'foo';\n    });\n\n    controller.plugins.cms.onChange('onboarding','name', async(value, convo, bot) => {\n        if (value === 'quit') {\n            convo.gotoThread('quit');\n        }\n    });\n\n    controller.plugins.cms.after('onboarding', async(results, bot) => {\n        // do something with results\n    });\n});\n```\n\n### Native Bot Builder Dialogs\n\n[BotBuilder dialogs](https://npmjs.com/package/botbuilder-dialogs) can live alongside Botkit!  Define dialogs using `WaterfallDialogs`, `ComponentDialogs`, or your own derived dialog class.  Then, make them available for your bot to use by calling `controller.addDialog()`:\n\n[Read about BotBuilder dialogs in Microsoft's official documentation &rarr;](https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-concept-dialog?view=azure-bot-service-4.0)\n\n```javascript\nconst { WaterfallDialog } = require('botbuilder-dialogs');\n\nconst myWelcomeDialog = new WaterfallDialog('welcome', [\n    async (step) => {\n        await step.context.sendActivity('Welcome!');\n        return await step.next();\n    },\n    async (step) => {\n        await step.context.sendActivity('Other do other stuff!');\n        return await step.next();\n    }\n]);\n\ncontroller.addDialog(myWelcomeDialog);\n```\n\nIn order to trigger the dialog from within a Botkit handler function, call `await bot.beginDialog('dialog_id');` as below:\n\n```javascript\nbotkit.hears(['hello'], 'message', async(bot, message) => {\n    await bot.beginDialog('welcome');\n});\n```\n\n### Enable Conversation Persistence\n\nBots that [use dialogs](#using-dialogs) for complex interactions require the ability to store and retrieve the conversation state from an external source such as a database. Without a storage mechanism in place, the bot will \"forget\" the state of conversations when the application is restarted.\n\nBotkit relies on [BotBuilder's storage protocol](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/storage?view=botbuilder-ts-latest) and a wide array of open source storage implementations to provide these features. Conversation state is managed automatically once enabled.\n\nOnce implemented, the state of a conversation will be persisted between restarts. In addition, when using a storage mechanism, bot applications can be deployed in multi-node, load balanced scenarios.\n\nBelow is an example of configuring Botkit to use MongoDB to store conversation state using [botbuilder-storage-mongodb](https://npmjs.com/package/botbuilder-storage-mongodb)\n\n```javascript\nconst { MongoDbStorage } = require('botbuilder-storage-mongodb');\nlet storage = mongoStorage = new MongoDbStorage({\n        url : process.env.MONGO_URI,\n});\nconst controller = new Botkit({\n    storage: storage\n});\n```\n\n[More storage implementations can be found by searching NPM for \"botbuilder-storage\" &rarr;](https://www.npmjs.com/search?q=botbuilder-storage)\n\n\n\n## Organize Your Bot Code\n\nThe [recommended application structure](advanced.md#anatomy-of-a-botkit-app) can created quickly by using the [Yeoman Generator](index.md#install-botkit)\nor one of the remixable starter kits.\n\nA Botkit application usually has 2 main components: a main app file called `bot.js` where Botkit is configured, and a folder of modules that get automatically loaded into the application.\n\nThe bot's features - all of the stuff involved in defining trigger patterns, dialogs, custom middlewares and handlers - are organized into JavaScript modules, and then loaded into the app using [controller.loadModules()](reference/core.md#loadmodules). If you are using Typescript, make sure to include `ts` extension into the second parameter as a string array (default is `['.js']`, and you probably want it to be `['.js', '.ts']`). Each feature file should contain only the code required for a specific feature. This will help to keep the project code well organized and modular.\n\nThe feature modules follow the form below:\n\n```javascript\nmodule.exports = function(controller) {\n\n    // define your dialogs, as well as your hears() or on() handlers\n    // ...\n}\n```\n\n## Using Bot Framework Channels\n\nBot Framework provides a unified interface to many different platforms, including Microsoft products like Microsoft Teams, Skype, Cortana, but also including platforms like Slack, and email. \n\nTo use Botkit with the Bot Framework channel service, pass in an `adapterConfig` parameter [matching this specification](https://docs.microsoft.com/en-us/javascript/api/botbuilder/botframeworkadaptersettings?view=botbuilder-ts-latest), and configure the channel service with the appropriate endpoint URL.\n\n```javascript\nconst controller = new Botkit({\n    webhook_uri: '/api/messages',\n    adapterConfig: {\n        appId: process.env.appId,\n        appPassword: process.env.appPassword\n    }\n});\n```\n\n## MS Teams Extensions\n\nSeveral helper extensions are included for using Botkit with Microsoft Teams. Connecting to Teams does not require a customized adapter - Botkit's default adapter does the job. However, to ease the use of advanced features in Teams, Botkit includes several extensions.\n\n* The [TeamsInvokeMiddleware](reference/core.md#teamsinvokemiddleware) is an optional adapter middleware which will cause Botkit to emit specially named events related to Teams \"invoke\" events. With this middleware enabled, Botkit will emit \"task/fetch\" and \"task/submit\" events, rather than plain \"invoke\" events.\n* The BotWorker returned by this adapter includes `bot.teams`, which is an instance of the TeamsInfo helper. Using this, bots can access additional information about Teams. [See Docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder/teamsinfo?view=botbuilder-ts-latest).\n* The BotWorker also includes a helper method, `bot.replyWithTaskInfo()` that can be used to respond to Task Module related events. [See Docs](reference/core.md#replywithtaskinfo)\n\nSet up adapter with middleware:\n\n```javascript\nconst controller = new Botkit({\n    webhook_uri: '/api/messages',\n    adapterConfig: {\n        appId: process.env.appId,\n        appPassword: process.env.appPassword\n    }\n});\ncontroller.adapter.use(new TeamsInvokeMiddleware());\n```\n\nAccess Teams specific APIs:\n```javascript\ncontroller.hears('getTeamDetails', 'message', async(bot, message) => {\n    try {\n    await bot.reply(message, JSON.stringify(await bot.teams.getTeamDetails(bot.getConfig('context'))));\n    } catch(err) {\n    await bot.reply(message, err.message);\n    }\n});\n```\n\nRespond to Task Modules:\n```javascript\ncontroller.on('task/fetch', async(bot, message) => {\n    await bot.replyWithTaskInfo(message, {type: 'continue', value: { ... }});\n});\n```\n\n## Building & Using Plugins\n\nBotkit includes a plugin loader that allows external packages to plugin to and modify the Botkit application.\n\nPlugins can:\n* Include middleware that is automatically applied\n* Make additional extension methods available for the bot to use\n* Add web routes to the application\n* Expose static assets to the web server\n* Define dialogs, triggers and handlers\n* Be packaged and published as self-contained JavaScript modules\n\nTo use a plugin, use `usePlugin()`:\n```javascript\nlet plugin = require('botkit-plugin-whatever');\ncontroller.usePlugin(plugin);\n``` \n\nA plugin module should contain an object (or a function that returns an object) in the form:\n```javascript\nmodule.exports = function(botkit) {\n\n    return {\n        // The name of the plugin. Used to log messages at boot time.\n        name: 'My Plugin',\n        // initialize this module. called at load time.\n        init: function(controller) {\n            // do things like:\n\n            // expose the methods from this plugin as controller.plugins.myplugin.<method>\n            // controller.addPluginExtension('myplugin', this);\n\n            // make locally bundled content public on the webservice:\n            // controller.publicFolder('/public/myplugin', __dirname + '/public);\n\n            // add a web route\n            // controller.webserver.get('/myplugin', async(req, res) => { \n            //      Use a local handlebars view (bundled with plugin) to render a page\n            //      (hbs must be installed and initialized by plugin)\n            //      res.render(controller.getLocalView(__dirname + '/views/main'));\n            // });\n\n            // can also define normal handlers\n            // controller.on('event', async(bot, message) => { ... });\n        },\n        // Any middlewares that should be automatically bound\n        // Can include more than 1 of each kind.\n        middlewares: {\n            ingest: [\n                (bot, message, next) => { next(); }\n            ],\n            receive: [\n                (bot, message, next) => { next(); }\n            ],\n            send: [\n                (bot, message, next) => { next(); }\n            ]\n        },\n        // this method will live at controller.plugins.myplugin.customMethod()\n        customMethod: async() => {}\n    }\n}\n```\n\nPlugin related methods:\n* [controller.usePlugin()](reference/core.md#useplugin)\n* [controller.addPluginExtension()](reference/core.md#addpluginextension)\n* [controller.getLocalView()](reference/core.md#getlocalview)\n* [controller.publicFolder()](reference/core.md#publicfolder)\n* [controller.plugins](reference/core.md#properties-and-accessors)\n\n## Middlewares\n\nBotkit middleware functions can be used to inspect and modify messages as they pass through.\nThere are a few types of middleware in the Botkit universe: \n\n* Botkit middleware - change the way Botkit itself handles messages\n* BotBuilder adapter middleware - change the way the platform translation layer handles messages\n* Webserver middleware - change the way the web server handles requests\n\n### Botkit Middleware\n\nMiddleware can do things like:\n* Log information about incoming and outgoing activity for debugging, analytics or other services\n* Amend messages with additional information - for example, call an NLP service and add an \"intent\" field\n* Intercept messages and prevent them from being processed\n* Change the type of the resulting event that will be emitted\n\nThere are three endpoints available to register middleware functions:\n\n| Name | Description\n|--- |---\n| ingest | occurs immediately after the message has been received, before any other processing\n| receive | occurs after the message has been evaluated for interruptions and for inclusion in an ongoing dialog. signals the receipt of a message that needs to be handled.\n| send | occurs just before a message is sent out of the bot to the messaging platform\n\nMiddleware functions are in the form:\n\n```javascript\nfunction myBotkitMiddleware(bot, message, next) { \n    // do stuff\n\n    // call next, or else the message will be intercepted\n    next();\n}\n```\n\nTo enable a middleware, register it at the appropriate endpoint:\n\n```javascript\ncontroller.middleware.ingest.use(myBotkitMiddleware);\n```\n\n### BotBuilder Adapter Middleware\n\nBotBuilder adapters like those used by Botkit also support middleware.  Some of the adapters included in the Botkit project use these middleware to modify the \"native\" BotBuilder activity objects along the way so that they play nicer with Botkit -- for example, see [SlackEventMiddleware](reference/slack.md#slackeventmiddleware).\n\nMiddleware for BotBuilder works on a similar principle as Botkit, but comes in a different form.\nIn addition, BotBuilder middleware work on Activity objects, not Botkit messages.  [Read more about BotBuilder middleware here &rarr;](https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-concept-middleware?view=azure-bot-service-4.0)\n\nBotBuilder middleware functions are in the form:\n```javascript\nasync function myBotBuilderMiddleware(turnContext, next) {\n\n    // do stuff with the turnContext BEFORE it is processed here\n\n    // call next, make sure to use await\n    // inside this next is where your whole bot does its thing!\n    await next();\n\n    // do stuff AFTER the message has been processed.\n}\n```\n\nTo enable a BotBuilder adapter middleware, register it on the adapter object:\n\n```javascript\nconst adapter = new WebAdapter();\nadapter.use(myBotBuilderMiddleware);\n```\n\n### Webserver Middleware\n\nWebserver middleware - specifically [Express middleware](https://expressjs.com/en/guide/using-middleware.html) - can be used for a variety of purposes including logging, authentication, and adding functionality that is automatically called when urls are requested from your webserver.\n\nExpress middleware look like this:\n\n```javascript\nfunction myExpressMiddleware(req, res, next) {\n    // do something useful.\n    // for example, you can modify req and res\n\n    // log the requested url. handy for debugging!\n    console.log('REQ: ', req.url);\n\n    // call next or else the request will be intercepted\n    next();\n}\n```\n\nTo enable an Express middleware, register it using `controller.webserver.use()`:\n\n```javascript\ncontroller.webserver.use(myExpressMiddleware);\n```\n"
  },
  {
    "path": "packages/docs/index.json",
    "content": "{\n  \"reference\": [\n    {\n      \"name\": \"Botkit Core\",\n      \"packageName\": \"botkit\",\n      \"path\": \"reference/core.md\",\n      \"classes\": [\n        {\n          \"id\": 185,\n          \"name\": \"Botkit\",\n          \"kind\": 128,\n          \"kindString\": \"Class\",\n          \"flags\": {\n            \"isExported\": true,\n            \"isExternal\": true\n          },\n          \"comment\": {\n            \"shortText\": \"Create a new instance of Botkit to define the controller for a conversational app.\\nTo connect Botkit to a chat platform, pass in a fully configured `adapter`.\\nIf one is not specified, Botkit will expose an adapter for the Microsoft Bot Framework.\"\n          },\n          \"children\": [\n            {\n              \"id\": 199,\n              \"name\": \"constructor\",\n              \"kind\": 512,\n              \"kindString\": \"Constructor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Create a new Botkit instance and optionally specify a platform-specific adapter.\\nBy default, Botkit will create a [BotFrameworkAdapter](https://docs.microsoft.com/en-us/javascript/api/botbuilder/botframeworkadapter?view=botbuilder-ts-latest).\",\n                \"text\": \"```javascript\\nconst controller = new Botkit({\\n     adapter: some_adapter,\\n     webhook_uri: '/api/messages',\\n});\\n\\ncontroller.on('message', async(bot, message) => {\\n     // do something!\\n});\\n```\\n\"\n              },\n              \"signatures\": [\n                {\n                  \"id\": 200,\n                  \"name\": \"new Botkit\",\n                  \"kind\": 16384,\n                  \"kindString\": \"Constructor signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Create a new Botkit instance and optionally specify a platform-specific adapter.\\nBy default, Botkit will create a [BotFrameworkAdapter](https://docs.microsoft.com/en-us/javascript/api/botbuilder/botframeworkadapter?view=botbuilder-ts-latest).\",\n                    \"text\": \"```javascript\\nconst controller = new Botkit({\\n     adapter: some_adapter,\\n     webhook_uri: '/api/messages',\\n});\\n\\ncontroller.on('message', async(bot, message) => {\\n     // do something!\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 201,\n                      \"name\": \"config\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"Configuration for this instance of Botkit\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 137,\n                        \"name\": \"BotkitConfiguration\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 185,\n                    \"name\": \"Botkit\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 310,\n                  \"character\": 28\n                }\n              ]\n            },\n            {\n              \"id\": 198,\n              \"name\": \"PATH\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"The path of the main Botkit SDK, used to generate relative paths\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 305,\n                  \"character\": 15\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 196,\n              \"name\": \"adapter\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Any BotBuilder-compatible adapter - defaults to a [BotFrameworkAdapter](https://docs.microsoft.com/en-us/javascript/api/botbuilder/botframeworkadapter?view=botbuilder-ts-latest)\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 295,\n                  \"character\": 18\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"any\"\n              }\n            },\n            {\n              \"id\": 197,\n              \"name\": \"dialogSet\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A BotBuilder DialogSet that serves as the top level dialog container for the Botkit app\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 300,\n                  \"character\": 20\n                }\n              ],\n              \"type\": {\n                \"type\": \"reference\",\n                \"name\": \"DialogSet\"\n              }\n            },\n            {\n              \"id\": 195,\n              \"name\": \"http\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A direct reference to the underlying HTTP server object\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 290,\n                  \"character\": 15\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"any\"\n              }\n            },\n            {\n              \"id\": 193,\n              \"name\": \"storage\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"a BotBuilder storage driver - defaults to MemoryStorage\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 280,\n                  \"character\": 18\n                }\n              ],\n              \"type\": {\n                \"type\": \"reference\",\n                \"name\": \"Storage\"\n              }\n            },\n            {\n              \"id\": 186,\n              \"name\": \"version\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"The current version of Botkit Core\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 240,\n                  \"character\": 18\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              },\n              \"defaultValue\": \"require('../package.json').version\"\n            },\n            {\n              \"id\": 194,\n              \"name\": \"webserver\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"An Express webserver\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 285,\n                  \"character\": 20\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"any\"\n              }\n            },\n            {\n              \"id\": 217,\n              \"name\": \"plugins\",\n              \"kind\": 262144,\n              \"kindString\": \"Accessor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Access plugin extension methods.\\nAfter a plugin calls `controller.addPluginExtension('foo', extension_methods)`, the extension will then be available at\\n`controller.plugins.foo`\"\n              },\n              \"getSignature\": [\n                {\n                  \"id\": 218,\n                  \"name\": \"__get\",\n                  \"kind\": 524288,\n                  \"kindString\": \"Get signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Access plugin extension methods.\\nAfter a plugin calls `controller.addPluginExtension('foo', extension_methods)`, the extension will then be available at\\n`controller.plugins.foo`\"\n                  },\n                  \"type\": {\n                    \"type\": \"reflection\",\n                    \"declaration\": {\n                      \"id\": 219,\n                      \"name\": \"__type\",\n                      \"kind\": 65536,\n                      \"kindString\": \"Type literal\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"indexSignature\": [\n                        {\n                          \"id\": 220,\n                          \"name\": \"__index\",\n                          \"kind\": 8192,\n                          \"kindString\": \"Index signature\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"parameters\": [\n                            {\n                              \"id\": 221,\n                              \"name\": \"key\",\n                              \"kind\": 32768,\n                              \"kindString\": \"Parameter\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"type\": {\n                                \"type\": \"intrinsic\",\n                                \"name\": \"string\"\n                              }\n                            }\n                          ],\n                          \"type\": {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"any\"\n                          }\n                        }\n                      ],\n                      \"sources\": [\n                        {\n                          \"fileName\": \"core.ts\",\n                          \"line\": 572,\n                          \"character\": 25\n                        }\n                      ]\n                    }\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 572,\n                  \"character\": 22\n                }\n              ]\n            },\n            {\n              \"id\": 229,\n              \"name\": \"addDep\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 230,\n                  \"name\": \"addDep\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"(For use by Botkit plugins only) - Add a dependency to Botkit's bootup process that must be marked as completed using `completeDep()`.\\nBotkit's `controller.ready()` function will not fire until all dependencies have been marked complete.\",\n                    \"text\": \"For example, a plugin that needs to do an asynchronous task before Botkit proceeds might do:\\n```javascript\\ncontroller.addDep('my_async_plugin');\\nsomethingAsync().then(function() {\\n controller.completeDep('my_async_plugin');\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 231,\n                      \"name\": \"name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"The name of the dependency that is being loaded.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 623,\n                  \"character\": 17\n                }\n              ]\n            },\n            {\n              \"id\": 288,\n              \"name\": \"addDialog\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 289,\n                  \"name\": \"addDialog\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Add a dialog to the bot, making it accessible via `bot.beginDialog(dialog_id)`\",\n                    \"text\": \"```javascript\\n// Create a dialog -- `BotkitConversation` is just one way to create a dialog\\nconst my_dialog = new BotkitConversation('my_dialog', controller);\\nmy_dialog.say('Hello');\\n\\n// Add the dialog to the Botkit controller\\ncontroller.addDialog(my_dialog);\\n\\n// Later on, trigger the dialog into action!\\ncontroller.on('message', async(bot, message) => {\\n     await bot.beginDialog('my_dialog');\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 290,\n                      \"name\": \"dialog\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A dialog to be added to the bot's dialog set\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"Dialog\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 1178,\n                  \"character\": 20\n                }\n              ]\n            },\n            {\n              \"id\": 213,\n              \"name\": \"addPluginExtension\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 214,\n                  \"name\": \"addPluginExtension\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"(Plugins only) Extend Botkit's controller with new functionality and make it available globally via the controller object.\",\n                    \"text\": \"```javascript\\n\\n// define the extension interface\\nlet extension = {\\n        stuff: () => { return 'stuff' }\\n}\\n\\n// register the extension\\ncontroller.addPluginExtension('foo', extension);\\n\\n// call extension\\ncontroller.plugins.foo.stuff();\\n\\n\\n```\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 215,\n                      \"name\": \"name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"name of plugin\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 216,\n                      \"name\": \"extension\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"an object containing methods\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 562,\n                  \"character\": 29\n                }\n              ]\n            },\n            {\n              \"id\": 291,\n              \"name\": \"afterDialog\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 292,\n                  \"name\": \"afterDialog\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Bind a handler to the end of a dialog.\\nNOTE: bot worker cannot use bot.reply(), must use bot.send()\",\n                    \"text\": \"[Learn more about handling end-of-conversation](../docs/conversations.md#handling-end-of-conversation)\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 293,\n                      \"name\": \"dialog\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"the dialog object or the id of the dialog\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"Dialog\"\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        ]\n                      }\n                    },\n                    {\n                      \"id\": 294,\n                      \"name\": \"handler\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"a handler function in the form `async(bot, dialog_results) => {}`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 162,\n                        \"name\": \"BotkitHandler\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 1205,\n                  \"character\": 22\n                }\n              ]\n            },\n            {\n              \"id\": 232,\n              \"name\": \"completeDep\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 233,\n                  \"name\": \"completeDep\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"(For use by plugins only) - Mark a bootup dependency as loaded and ready to use\\nBotkit's `controller.ready()` function will not fire until all dependencies have been marked complete.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 234,\n                      \"name\": \"name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"The name of the dependency that has completed loading.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"boolean\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 634,\n                  \"character\": 22\n                }\n              ]\n            },\n            {\n              \"id\": 204,\n              \"name\": \"getConfig\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 205,\n                  \"name\": \"getConfig\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Get a value from the configuration.\",\n                    \"text\": \"For example:\\n```javascript\\n// get entire config object\\nlet config = controller.getConfig();\\n\\n// get a specific value from the config\\nlet webhook_uri = controller.getConfig('webhook_uri');\\n```\\n\",\n                    \"returns\": \"The value stored in the configuration (or null if absent)\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 206,\n                      \"name\": \"key\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"The name of a value stored in the configuration\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"any\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 477,\n                  \"character\": 20\n                }\n              ]\n            },\n            {\n              \"id\": 226,\n              \"name\": \"getLocalView\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 227,\n                  \"name\": \"getLocalView\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Convert a local path from a plugin folder to a full path relative to the webserver's main views folder.\\nAllows a plugin to bundle views/layouts and make them available to the webserver's renderer.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 228,\n                      \"name\": \"path_to_view\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"something like path.join(__dirname,'views')\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"string\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 601,\n                  \"character\": 23\n                }\n              ]\n            },\n            {\n              \"id\": 240,\n              \"name\": \"handleTurn\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 241,\n                  \"name\": \"handleTurn\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Accepts the result of a BotBuilder adapter's `processActivity()` method and processes it into a Botkit-style message and BotWorker instance\\nwhich is then used to test for triggers and emit events.\\nNOTE: This method should only be used in custom adapters that receive messages through mechanisms other than the main webhook endpoint (such as those received via websocket, for example)\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 242,\n                      \"name\": \"turnContext\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"a TurnContext representing an incoming message, typically created by an adapter's `processActivity()` method.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"TurnContext\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 711,\n                  \"character\": 27\n                }\n              ]\n            },\n            {\n              \"id\": 246,\n              \"name\": \"hears\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 247,\n                  \"name\": \"hears\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Instruct your bot to listen for a pattern, and do something when that pattern is heard.\\nPatterns will be \\\"heard\\\" only if the message is not already handled by an in-progress dialog.\\nTo \\\"hear\\\" patterns _before_ dialogs are processed, use `controller.interrupts()` instead.\",\n                    \"text\": \"For example:\\n```javascript\\n// listen for a simple keyword\\ncontroller.hears('hello','message', async(bot, message) => {\\n await bot.reply(message,'I heard you say hello.');\\n});\\n\\n// listen for a regular expression\\ncontroller.hears(new RegExp(/^[A-Z\\\\s]+$/), 'message', async(bot, message) => {\\n await bot.reply(message,'I heard a message IN ALL CAPS.');\\n});\\n\\n// listen using a function\\ncontroller.hears(async (message) => { return (message.intent === 'hello') }, 'message', async(bot, message) => {\\n await bot.reply(message,'This message matches the hello intent.');\\n});\\n```\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 248,\n                      \"name\": \"patterns\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"One or more string, regular expression, or test function\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"array\",\n                            \"elementType\": {\n                              \"type\": \"union\",\n                              \"types\": [\n                                {\n                                  \"type\": \"intrinsic\",\n                                  \"name\": \"string\"\n                                },\n                                {\n                                  \"type\": \"reference\",\n                                  \"name\": \"RegExp\"\n                                },\n                                {\n                                  \"type\": \"reflection\",\n                                  \"declaration\": {\n                                    \"id\": 249,\n                                    \"name\": \"__type\",\n                                    \"kind\": 65536,\n                                    \"kindString\": \"Type literal\",\n                                    \"flags\": {\n                                      \"isExported\": true\n                                    },\n                                    \"signatures\": [\n                                      {\n                                        \"id\": 250,\n                                        \"name\": \"__call\",\n                                        \"kind\": 4096,\n                                        \"kindString\": \"Call signature\",\n                                        \"flags\": {\n                                          \"isExported\": true\n                                        },\n                                        \"parameters\": [\n                                          {\n                                            \"id\": 251,\n                                            \"name\": \"message\",\n                                            \"kind\": 32768,\n                                            \"kindString\": \"Parameter\",\n                                            \"flags\": {\n                                              \"isExported\": true\n                                            },\n                                            \"type\": {\n                                              \"type\": \"reference\",\n                                              \"id\": 152,\n                                              \"name\": \"BotkitMessage\"\n                                            }\n                                          }\n                                        ],\n                                        \"type\": {\n                                          \"type\": \"reference\",\n                                          \"typeArguments\": [\n                                            {\n                                              \"type\": \"intrinsic\",\n                                              \"name\": \"boolean\"\n                                            }\n                                          ],\n                                          \"name\": \"Promise\"\n                                        }\n                                      }\n                                    ]\n                                  }\n                                }\n                              ]\n                            }\n                          },\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"RegExp\"\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          },\n                          {\n                            \"type\": \"reflection\",\n                            \"declaration\": {\n                              \"id\": 252,\n                              \"name\": \"__type\",\n                              \"kind\": 65536,\n                              \"kindString\": \"Type literal\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"signatures\": [\n                                {\n                                  \"id\": 253,\n                                  \"name\": \"__call\",\n                                  \"kind\": 4096,\n                                  \"kindString\": \"Call signature\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"parameters\": [\n                                    {\n                                      \"id\": 254,\n                                      \"name\": \"message\",\n                                      \"kind\": 32768,\n                                      \"kindString\": \"Parameter\",\n                                      \"flags\": {\n                                        \"isExported\": true\n                                      },\n                                      \"type\": {\n                                        \"type\": \"reference\",\n                                        \"id\": 152,\n                                        \"name\": \"BotkitMessage\"\n                                      }\n                                    }\n                                  ],\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"typeArguments\": [\n                                      {\n                                        \"type\": \"intrinsic\",\n                                        \"name\": \"boolean\"\n                                      }\n                                    ],\n                                    \"name\": \"Promise\"\n                                  }\n                                }\n                              ],\n                              \"sources\": [\n                                {\n                                  \"fileName\": \"core.ts\",\n                                  \"line\": 912,\n                                  \"character\": 115\n                                }\n                              ]\n                            }\n                          }\n                        ]\n                      }\n                    },\n                    {\n                      \"id\": 255,\n                      \"name\": \"events\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A list of event types that should be evaluated for the given patterns\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          },\n                          {\n                            \"type\": \"array\",\n                            \"elementType\": {\n                              \"type\": \"intrinsic\",\n                              \"name\": \"string\"\n                            }\n                          }\n                        ]\n                      }\n                    },\n                    {\n                      \"id\": 256,\n                      \"name\": \"handler\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"a function that will be called should the pattern be matched\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 162,\n                        \"name\": \"BotkitHandler\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 912,\n                  \"character\": 16\n                }\n              ]\n            },\n            {\n              \"id\": 257,\n              \"name\": \"interrupts\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 258,\n                  \"name\": \"interrupts\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Instruct your bot to listen for a pattern, and do something when that pattern is heard.\\nInterruptions work just like \\\"hears\\\" triggers, but fire _before_ the dialog system is engaged,\\nand thus handlers will interrupt the normal flow of messages through the processing pipeline.\",\n                    \"text\": \"```javascript\\ncontroller.interrupts('help','message', async(bot, message) => {\\n\\n await bot.reply(message,'Before anything else, you need some help!')\\n\\n});\\n```\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 259,\n                      \"name\": \"patterns\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"One or more string, regular expression, or test function\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"array\",\n                            \"elementType\": {\n                              \"type\": \"union\",\n                              \"types\": [\n                                {\n                                  \"type\": \"intrinsic\",\n                                  \"name\": \"string\"\n                                },\n                                {\n                                  \"type\": \"reference\",\n                                  \"name\": \"RegExp\"\n                                },\n                                {\n                                  \"type\": \"reflection\",\n                                  \"declaration\": {\n                                    \"id\": 260,\n                                    \"name\": \"__type\",\n                                    \"kind\": 65536,\n                                    \"kindString\": \"Type literal\",\n                                    \"flags\": {\n                                      \"isExported\": true\n                                    },\n                                    \"signatures\": [\n                                      {\n                                        \"id\": 261,\n                                        \"name\": \"__call\",\n                                        \"kind\": 4096,\n                                        \"kindString\": \"Call signature\",\n                                        \"flags\": {\n                                          \"isExported\": true\n                                        },\n                                        \"parameters\": [\n                                          {\n                                            \"id\": 262,\n                                            \"name\": \"message\",\n                                            \"kind\": 32768,\n                                            \"kindString\": \"Parameter\",\n                                            \"flags\": {\n                                              \"isExported\": true\n                                            },\n                                            \"type\": {\n                                              \"type\": \"reference\",\n                                              \"id\": 152,\n                                              \"name\": \"BotkitMessage\"\n                                            }\n                                          }\n                                        ],\n                                        \"type\": {\n                                          \"type\": \"reference\",\n                                          \"typeArguments\": [\n                                            {\n                                              \"type\": \"intrinsic\",\n                                              \"name\": \"boolean\"\n                                            }\n                                          ],\n                                          \"name\": \"Promise\"\n                                        }\n                                      }\n                                    ]\n                                  }\n                                }\n                              ]\n                            }\n                          },\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"RegExp\"\n                          },\n                          {\n                            \"type\": \"array\",\n                            \"elementType\": {\n                              \"type\": \"reference\",\n                              \"name\": \"RegExp\"\n                            }\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          },\n                          {\n                            \"type\": \"reflection\",\n                            \"declaration\": {\n                              \"id\": 263,\n                              \"name\": \"__type\",\n                              \"kind\": 65536,\n                              \"kindString\": \"Type literal\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"signatures\": [\n                                {\n                                  \"id\": 264,\n                                  \"name\": \"__call\",\n                                  \"kind\": 4096,\n                                  \"kindString\": \"Call signature\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"parameters\": [\n                                    {\n                                      \"id\": 265,\n                                      \"name\": \"message\",\n                                      \"kind\": 32768,\n                                      \"kindString\": \"Parameter\",\n                                      \"flags\": {\n                                        \"isExported\": true\n                                      },\n                                      \"type\": {\n                                        \"type\": \"reference\",\n                                        \"id\": 152,\n                                        \"name\": \"BotkitMessage\"\n                                      }\n                                    }\n                                  ],\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"typeArguments\": [\n                                      {\n                                        \"type\": \"intrinsic\",\n                                        \"name\": \"boolean\"\n                                      }\n                                    ],\n                                    \"name\": \"Promise\"\n                                  }\n                                }\n                              ],\n                              \"sources\": [\n                                {\n                                  \"fileName\": \"core.ts\",\n                                  \"line\": 967,\n                                  \"character\": 131\n                                }\n                              ]\n                            }\n                          }\n                        ]\n                      }\n                    },\n                    {\n                      \"id\": 266,\n                      \"name\": \"events\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A list of event types that should be evaluated for the given patterns\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          },\n                          {\n                            \"type\": \"array\",\n                            \"elementType\": {\n                              \"type\": \"intrinsic\",\n                              \"name\": \"string\"\n                            }\n                          }\n                        ]\n                      }\n                    },\n                    {\n                      \"id\": 267,\n                      \"name\": \"handler\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"a function that will be called should the pattern be matched\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 162,\n                        \"name\": \"BotkitHandler\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 967,\n                  \"character\": 21\n                }\n              ]\n            },\n            {\n              \"id\": 281,\n              \"name\": \"loadModule\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 282,\n                  \"name\": \"loadModule\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Load a Botkit feature module\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 283,\n                      \"name\": \"p\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"path to module file\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 1121,\n                  \"character\": 21\n                }\n              ]\n            },\n            {\n              \"id\": 284,\n              \"name\": \"loadModules\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 285,\n                  \"name\": \"loadModules\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Load all Botkit feature modules located in a given folder.\",\n                    \"text\": \"```javascript\\ncontroller.ready(() => {\\n\\n // load all modules from sub-folder features/\\n controller.loadModules('./features');\\n\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 286,\n                      \"name\": \"p\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"path to a folder of module files\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 287,\n                      \"name\": \"exts\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"the extensions that you would like to load (default: ['.js'])\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"intrinsic\",\n                          \"name\": \"string\"\n                        }\n                      },\n                      \"defaultValue\": \"['.js']\"\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 1150,\n                  \"character\": 22\n                }\n              ]\n            },\n            {\n              \"id\": 268,\n              \"name\": \"on\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 269,\n                  \"name\": \"on\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Bind a handler function to one or more events.\",\n                    \"text\": \"```javascript\\ncontroller.on('conversationUpdate', async(bot, message) => {\\n\\n await bot.reply(message,'I received a conversationUpdate event.');\\n\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 270,\n                      \"name\": \"events\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"One or more event names\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          },\n                          {\n                            \"type\": \"array\",\n                            \"elementType\": {\n                              \"type\": \"intrinsic\",\n                              \"name\": \"string\"\n                            }\n                          }\n                        ]\n                      }\n                    },\n                    {\n                      \"id\": 271,\n                      \"name\": \"handler\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"a handler function that will fire whenever one of the named events is received.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 162,\n                        \"name\": \"BotkitHandler\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 1019,\n                  \"character\": 13\n                }\n              ]\n            },\n            {\n              \"id\": 222,\n              \"name\": \"publicFolder\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 223,\n                  \"name\": \"publicFolder\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Expose a folder to the web as a set of static files.\\nUseful for plugins that need to bundle additional assets!\",\n                    \"text\": \"```javascript\\n// make content of the local public folder available at http://MYBOTURL/public/myplugin\\ncontroller.publicFolder('/public/myplugin', __dirname + '/public);\\n```\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 224,\n                      \"name\": \"alias\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"the public alias ie /myfiles\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 225,\n                      \"name\": \"path\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"the actual path something like `__dirname + '/public'`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 587,\n                  \"character\": 23\n                }\n              ]\n            },\n            {\n              \"id\": 235,\n              \"name\": \"ready\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 236,\n                  \"name\": \"ready\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Use `controller.ready()` to wrap any calls that require components loaded during the bootup process.\\nThis will ensure that the calls will not be made until all of the components have successfully been initialized.\",\n                    \"text\": \"For example:\\n```javascript\\ncontroller.ready(() => {\\n\\n  controller.loadModules(__dirname + '/features');\\n\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 237,\n                      \"name\": \"handler\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A function to run when Botkit is booted and ready to run.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 238,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 239,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"type\": {\n                                \"type\": \"intrinsic\",\n                                \"name\": \"any\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"core.ts\",\n                              \"line\": 676,\n                              \"character\": 25\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 676,\n                  \"character\": 16\n                }\n              ]\n            },\n            {\n              \"id\": 243,\n              \"name\": \"saveState\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 244,\n                  \"name\": \"saveState\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Save the current conversation state pertaining to a given BotWorker's activities.\\nNote: this is normally called internally and is only required when state changes happen outside of the normal processing flow.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 245,\n                      \"name\": \"bot\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"a BotWorker instance created using `controller.spawn()`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 2,\n                        \"name\": \"BotWorker\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 783,\n                  \"character\": 26\n                }\n              ]\n            },\n            {\n              \"id\": 202,\n              \"name\": \"shutdown\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 203,\n                  \"name\": \"shutdown\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Shutdown the webserver and prepare to terminate the app.\\nCauses Botkit to first emit a special `shutdown` event, process any bound handlers, and then finally terminate the webserver.\\nBind any necessary cleanup helpers to the shutdown event - for example, close the connection to mongo.\",\n                    \"text\": \"```javascript\\nawait controller.shutdown();\\ncontroller.on('shutdown', async() => {\\n     console.log('Bot is shutting down!');\\n});\\n```\\n\"\n                  },\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 453,\n                  \"character\": 25\n                }\n              ]\n            },\n            {\n              \"id\": 277,\n              \"name\": \"spawn\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 278,\n                  \"name\": \"spawn\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Create a platform-specific BotWorker instance that can be used to respond to messages or generate new outbound messages.\\nThe spawned `bot` contains all information required to process outbound messages and handle dialog state, and may also contain extensions\\nfor handling platform-specific events or activities.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 279,\n                      \"name\": \"config\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"Preferably receives a DialogContext, though can also receive a TurnContext. If excluded, must call `bot.changeContext(reference)` before calling any other method.\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 280,\n                      \"name\": \"custom_adapter\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"BotAdapter\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"reference\",\n                        \"id\": 2,\n                        \"name\": \"BotWorker\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 1075,\n                  \"character\": 22\n                }\n              ]\n            },\n            {\n              \"id\": 272,\n              \"name\": \"trigger\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 273,\n                  \"name\": \"trigger\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Trigger an event to be fired.  This will cause any bound handlers to be executed.\\nNote: This is normally used internally, but can be used to emit custom events.\",\n                    \"text\": \"```javascript\\n// fire a custom event\\ncontroller.trigger('my_custom_event', bot, message);\\n\\n// handle the custom event\\ncontroller.on('my_custom_event', async(bot, message) => {\\n //... do something\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 274,\n                      \"name\": \"event\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"the name of the event\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 275,\n                      \"name\": \"bot\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"a BotWorker instance created using `controller.spawn()`\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 2,\n                        \"name\": \"BotWorker\"\n                      }\n                    },\n                    {\n                      \"id\": 276,\n                      \"name\": \"message\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An incoming message or event\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 152,\n                        \"name\": \"BotkitMessage\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 1051,\n                  \"character\": 24\n                }\n              ]\n            },\n            {\n              \"id\": 207,\n              \"name\": \"usePlugin\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 208,\n                  \"name\": \"usePlugin\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Load a plugin module and bind all included middlewares to their respective endpoints.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 209,\n                      \"name\": \"plugin_or_function\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A plugin module in the form of function(botkit) {...} that returns {name, middlewares, init} or an object in the same form.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"reflection\",\n                            \"declaration\": {\n                              \"id\": 210,\n                              \"name\": \"__type\",\n                              \"kind\": 65536,\n                              \"kindString\": \"Type literal\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"signatures\": [\n                                {\n                                  \"id\": 211,\n                                  \"name\": \"__call\",\n                                  \"kind\": 4096,\n                                  \"kindString\": \"Call signature\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"parameters\": [\n                                    {\n                                      \"id\": 212,\n                                      \"name\": \"botkit\",\n                                      \"kind\": 32768,\n                                      \"kindString\": \"Parameter\",\n                                      \"flags\": {\n                                        \"isExported\": true\n                                      },\n                                      \"type\": {\n                                        \"type\": \"reference\",\n                                        \"id\": 185,\n                                        \"name\": \"Botkit\"\n                                      }\n                                    }\n                                  ],\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"id\": 173,\n                                    \"name\": \"BotkitPlugin\"\n                                  }\n                                }\n                              ],\n                              \"sources\": [\n                                {\n                                  \"fileName\": \"core.ts\",\n                                  \"line\": 489,\n                                  \"character\": 40\n                                }\n                              ]\n                            }\n                          },\n                          {\n                            \"type\": \"reference\",\n                            \"id\": 173,\n                            \"name\": \"BotkitPlugin\"\n                          }\n                        ]\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 489,\n                  \"character\": 20\n                }\n              ]\n            },\n            {\n              \"id\": 187,\n              \"name\": \"middleware\",\n              \"kind\": 2097152,\n              \"kindString\": \"Object literal\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Middleware endpoints available for plugins and features to extend Botkit.\\nEndpoints available are: spawn, ingest, receive, send.\",\n                \"text\": \"To bind a middleware function to Botkit:\\n```javascript\\ncontroller.middleware.receive.use(function(bot, message, next) {\\n\\n // do something with bot or message\\n\\n // always call next, or your bot will freeze!\\n next();\\n});\\n```\\n\"\n              },\n              \"children\": [\n                {\n                  \"id\": 189,\n                  \"name\": \"ingest\",\n                  \"kind\": 32,\n                  \"kindString\": \"Variable\",\n                  \"flags\": {\n                    \"isExported\": true,\n                    \"isExternal\": true\n                  },\n                  \"sources\": [\n                    {\n                      \"fileName\": \"core.ts\",\n                      \"line\": 259,\n                      \"character\": 14\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"any\"\n                  },\n                  \"defaultValue\": \"new Ware()\"\n                },\n                {\n                  \"id\": 192,\n                  \"name\": \"interpret\",\n                  \"kind\": 32,\n                  \"kindString\": \"Variable\",\n                  \"flags\": {\n                    \"isExported\": true,\n                    \"isExternal\": true\n                  },\n                  \"sources\": [\n                    {\n                      \"fileName\": \"core.ts\",\n                      \"line\": 262,\n                      \"character\": 17\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"any\"\n                  },\n                  \"defaultValue\": \"new Ware()\"\n                },\n                {\n                  \"id\": 191,\n                  \"name\": \"receive\",\n                  \"kind\": 32,\n                  \"kindString\": \"Variable\",\n                  \"flags\": {\n                    \"isExported\": true,\n                    \"isExternal\": true\n                  },\n                  \"sources\": [\n                    {\n                      \"fileName\": \"core.ts\",\n                      \"line\": 261,\n                      \"character\": 15\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"any\"\n                  },\n                  \"defaultValue\": \"new Ware()\"\n                },\n                {\n                  \"id\": 190,\n                  \"name\": \"send\",\n                  \"kind\": 32,\n                  \"kindString\": \"Variable\",\n                  \"flags\": {\n                    \"isExported\": true,\n                    \"isExternal\": true\n                  },\n                  \"sources\": [\n                    {\n                      \"fileName\": \"core.ts\",\n                      \"line\": 260,\n                      \"character\": 12\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"any\"\n                  },\n                  \"defaultValue\": \"new Ware()\"\n                },\n                {\n                  \"id\": 188,\n                  \"name\": \"spawn\",\n                  \"kind\": 32,\n                  \"kindString\": \"Variable\",\n                  \"flags\": {\n                    \"isExported\": true,\n                    \"isExternal\": true\n                  },\n                  \"sources\": [\n                    {\n                      \"fileName\": \"core.ts\",\n                      \"line\": 258,\n                      \"character\": 13\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"any\"\n                  },\n                  \"defaultValue\": \"new Ware()\"\n                }\n              ],\n              \"groups\": [\n                {\n                  \"title\": \"Variables\",\n                  \"kind\": 32,\n                  \"children\": [\n                    189,\n                    192,\n                    191,\n                    190,\n                    188\n                  ]\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 257,\n                  \"character\": 21\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"object\"\n              }\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Constructors\",\n              \"kind\": 512,\n              \"children\": [\n                199\n              ]\n            },\n            {\n              \"title\": \"Properties\",\n              \"kind\": 1024,\n              \"children\": [\n                198,\n                196,\n                197,\n                195,\n                193,\n                186,\n                194\n              ]\n            },\n            {\n              \"title\": \"Accessors\",\n              \"kind\": 262144,\n              \"children\": [\n                217\n              ]\n            },\n            {\n              \"title\": \"Methods\",\n              \"kind\": 2048,\n              \"children\": [\n                229,\n                288,\n                213,\n                291,\n                232,\n                204,\n                226,\n                240,\n                246,\n                257,\n                281,\n                284,\n                268,\n                222,\n                235,\n                243,\n                202,\n                277,\n                272,\n                207\n              ]\n            },\n            {\n              \"title\": \"Object literals\",\n              \"kind\": 2097152,\n              \"children\": [\n                187\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"core.ts\",\n              \"line\": 187,\n              \"character\": 19\n            }\n          ],\n          \"props\": [\n            {\n              \"id\": 198,\n              \"name\": \"PATH\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"The path of the main Botkit SDK, used to generate relative paths\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 305,\n                  \"character\": 15\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 196,\n              \"name\": \"adapter\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Any BotBuilder-compatible adapter - defaults to a [BotFrameworkAdapter](https://docs.microsoft.com/en-us/javascript/api/botbuilder/botframeworkadapter?view=botbuilder-ts-latest)\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 295,\n                  \"character\": 18\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"any\"\n              }\n            },\n            {\n              \"id\": 197,\n              \"name\": \"dialogSet\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A BotBuilder DialogSet that serves as the top level dialog container for the Botkit app\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 300,\n                  \"character\": 20\n                }\n              ],\n              \"type\": {\n                \"type\": \"reference\",\n                \"name\": \"DialogSet\"\n              }\n            },\n            {\n              \"id\": 195,\n              \"name\": \"http\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A direct reference to the underlying HTTP server object\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 290,\n                  \"character\": 15\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"any\"\n              }\n            },\n            {\n              \"id\": 193,\n              \"name\": \"storage\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"a BotBuilder storage driver - defaults to MemoryStorage\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 280,\n                  \"character\": 18\n                }\n              ],\n              \"type\": {\n                \"type\": \"reference\",\n                \"name\": \"Storage\"\n              }\n            },\n            {\n              \"id\": 186,\n              \"name\": \"version\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"The current version of Botkit Core\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 240,\n                  \"character\": 18\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              },\n              \"defaultValue\": \"require('../package.json').version\"\n            },\n            {\n              \"id\": 194,\n              \"name\": \"webserver\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"An Express webserver\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 285,\n                  \"character\": 20\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"any\"\n              }\n            },\n            {\n              \"id\": 217,\n              \"name\": \"plugins\",\n              \"kind\": 262144,\n              \"kindString\": \"Accessor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Access plugin extension methods.\\nAfter a plugin calls `controller.addPluginExtension('foo', extension_methods)`, the extension will then be available at\\n`controller.plugins.foo`\"\n              },\n              \"getSignature\": [\n                {\n                  \"id\": 218,\n                  \"name\": \"__get\",\n                  \"kind\": 524288,\n                  \"kindString\": \"Get signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Access plugin extension methods.\\nAfter a plugin calls `controller.addPluginExtension('foo', extension_methods)`, the extension will then be available at\\n`controller.plugins.foo`\"\n                  },\n                  \"type\": {\n                    \"type\": \"reflection\",\n                    \"declaration\": {\n                      \"id\": 219,\n                      \"name\": \"__type\",\n                      \"kind\": 65536,\n                      \"kindString\": \"Type literal\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"indexSignature\": [\n                        {\n                          \"id\": 220,\n                          \"name\": \"__index\",\n                          \"kind\": 8192,\n                          \"kindString\": \"Index signature\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"parameters\": [\n                            {\n                              \"id\": 221,\n                              \"name\": \"key\",\n                              \"kind\": 32768,\n                              \"kindString\": \"Parameter\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"type\": {\n                                \"type\": \"intrinsic\",\n                                \"name\": \"string\"\n                              }\n                            }\n                          ],\n                          \"type\": {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"any\"\n                          }\n                        }\n                      ],\n                      \"sources\": [\n                        {\n                          \"fileName\": \"core.ts\",\n                          \"line\": 572,\n                          \"character\": 25\n                        }\n                      ]\n                    }\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 572,\n                  \"character\": 22\n                }\n              ]\n            }\n          ],\n          \"methods\": [\n            {\n              \"id\": 229,\n              \"name\": \"addDep\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 230,\n                  \"name\": \"addDep\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"(For use by Botkit plugins only) - Add a dependency to Botkit's bootup process that must be marked as completed using `completeDep()`.\\nBotkit's `controller.ready()` function will not fire until all dependencies have been marked complete.\",\n                    \"text\": \"For example, a plugin that needs to do an asynchronous task before Botkit proceeds might do:\\n```javascript\\ncontroller.addDep('my_async_plugin');\\nsomethingAsync().then(function() {\\n controller.completeDep('my_async_plugin');\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 231,\n                      \"name\": \"name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"The name of the dependency that is being loaded.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 623,\n                  \"character\": 17\n                }\n              ]\n            },\n            {\n              \"id\": 288,\n              \"name\": \"addDialog\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 289,\n                  \"name\": \"addDialog\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Add a dialog to the bot, making it accessible via `bot.beginDialog(dialog_id)`\",\n                    \"text\": \"```javascript\\n// Create a dialog -- `BotkitConversation` is just one way to create a dialog\\nconst my_dialog = new BotkitConversation('my_dialog', controller);\\nmy_dialog.say('Hello');\\n\\n// Add the dialog to the Botkit controller\\ncontroller.addDialog(my_dialog);\\n\\n// Later on, trigger the dialog into action!\\ncontroller.on('message', async(bot, message) => {\\n     await bot.beginDialog('my_dialog');\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 290,\n                      \"name\": \"dialog\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A dialog to be added to the bot's dialog set\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"Dialog\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 1178,\n                  \"character\": 20\n                }\n              ]\n            },\n            {\n              \"id\": 213,\n              \"name\": \"addPluginExtension\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 214,\n                  \"name\": \"addPluginExtension\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"(Plugins only) Extend Botkit's controller with new functionality and make it available globally via the controller object.\",\n                    \"text\": \"```javascript\\n\\n// define the extension interface\\nlet extension = {\\n        stuff: () => { return 'stuff' }\\n}\\n\\n// register the extension\\ncontroller.addPluginExtension('foo', extension);\\n\\n// call extension\\ncontroller.plugins.foo.stuff();\\n\\n\\n```\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 215,\n                      \"name\": \"name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"name of plugin\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 216,\n                      \"name\": \"extension\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"an object containing methods\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 562,\n                  \"character\": 29\n                }\n              ]\n            },\n            {\n              \"id\": 291,\n              \"name\": \"afterDialog\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 292,\n                  \"name\": \"afterDialog\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Bind a handler to the end of a dialog.\\nNOTE: bot worker cannot use bot.reply(), must use bot.send()\",\n                    \"text\": \"[Learn more about handling end-of-conversation](../docs/conversations.md#handling-end-of-conversation)\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 293,\n                      \"name\": \"dialog\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"the dialog object or the id of the dialog\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"Dialog\"\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        ]\n                      }\n                    },\n                    {\n                      \"id\": 294,\n                      \"name\": \"handler\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"a handler function in the form `async(bot, dialog_results) => {}`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 162,\n                        \"name\": \"BotkitHandler\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 1205,\n                  \"character\": 22\n                }\n              ]\n            },\n            {\n              \"id\": 232,\n              \"name\": \"completeDep\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 233,\n                  \"name\": \"completeDep\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"(For use by plugins only) - Mark a bootup dependency as loaded and ready to use\\nBotkit's `controller.ready()` function will not fire until all dependencies have been marked complete.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 234,\n                      \"name\": \"name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"The name of the dependency that has completed loading.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"boolean\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 634,\n                  \"character\": 22\n                }\n              ]\n            },\n            {\n              \"id\": 204,\n              \"name\": \"getConfig\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 205,\n                  \"name\": \"getConfig\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Get a value from the configuration.\",\n                    \"text\": \"For example:\\n```javascript\\n// get entire config object\\nlet config = controller.getConfig();\\n\\n// get a specific value from the config\\nlet webhook_uri = controller.getConfig('webhook_uri');\\n```\\n\",\n                    \"returns\": \"The value stored in the configuration (or null if absent)\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 206,\n                      \"name\": \"key\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"The name of a value stored in the configuration\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"any\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 477,\n                  \"character\": 20\n                }\n              ]\n            },\n            {\n              \"id\": 226,\n              \"name\": \"getLocalView\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 227,\n                  \"name\": \"getLocalView\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Convert a local path from a plugin folder to a full path relative to the webserver's main views folder.\\nAllows a plugin to bundle views/layouts and make them available to the webserver's renderer.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 228,\n                      \"name\": \"path_to_view\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"something like path.join(__dirname,'views')\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"string\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 601,\n                  \"character\": 23\n                }\n              ]\n            },\n            {\n              \"id\": 240,\n              \"name\": \"handleTurn\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 241,\n                  \"name\": \"handleTurn\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Accepts the result of a BotBuilder adapter's `processActivity()` method and processes it into a Botkit-style message and BotWorker instance\\nwhich is then used to test for triggers and emit events.\\nNOTE: This method should only be used in custom adapters that receive messages through mechanisms other than the main webhook endpoint (such as those received via websocket, for example)\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 242,\n                      \"name\": \"turnContext\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"a TurnContext representing an incoming message, typically created by an adapter's `processActivity()` method.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"TurnContext\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 711,\n                  \"character\": 27\n                }\n              ]\n            },\n            {\n              \"id\": 246,\n              \"name\": \"hears\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 247,\n                  \"name\": \"hears\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Instruct your bot to listen for a pattern, and do something when that pattern is heard.\\nPatterns will be \\\"heard\\\" only if the message is not already handled by an in-progress dialog.\\nTo \\\"hear\\\" patterns _before_ dialogs are processed, use `controller.interrupts()` instead.\",\n                    \"text\": \"For example:\\n```javascript\\n// listen for a simple keyword\\ncontroller.hears('hello','message', async(bot, message) => {\\n await bot.reply(message,'I heard you say hello.');\\n});\\n\\n// listen for a regular expression\\ncontroller.hears(new RegExp(/^[A-Z\\\\s]+$/), 'message', async(bot, message) => {\\n await bot.reply(message,'I heard a message IN ALL CAPS.');\\n});\\n\\n// listen using a function\\ncontroller.hears(async (message) => { return (message.intent === 'hello') }, 'message', async(bot, message) => {\\n await bot.reply(message,'This message matches the hello intent.');\\n});\\n```\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 248,\n                      \"name\": \"patterns\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"One or more string, regular expression, or test function\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"array\",\n                            \"elementType\": {\n                              \"type\": \"union\",\n                              \"types\": [\n                                {\n                                  \"type\": \"intrinsic\",\n                                  \"name\": \"string\"\n                                },\n                                {\n                                  \"type\": \"reference\",\n                                  \"name\": \"RegExp\"\n                                },\n                                {\n                                  \"type\": \"reflection\",\n                                  \"declaration\": {\n                                    \"id\": 249,\n                                    \"name\": \"__type\",\n                                    \"kind\": 65536,\n                                    \"kindString\": \"Type literal\",\n                                    \"flags\": {\n                                      \"isExported\": true\n                                    },\n                                    \"signatures\": [\n                                      {\n                                        \"id\": 250,\n                                        \"name\": \"__call\",\n                                        \"kind\": 4096,\n                                        \"kindString\": \"Call signature\",\n                                        \"flags\": {\n                                          \"isExported\": true\n                                        },\n                                        \"parameters\": [\n                                          {\n                                            \"id\": 251,\n                                            \"name\": \"message\",\n                                            \"kind\": 32768,\n                                            \"kindString\": \"Parameter\",\n                                            \"flags\": {\n                                              \"isExported\": true\n                                            },\n                                            \"type\": {\n                                              \"type\": \"reference\",\n                                              \"id\": 152,\n                                              \"name\": \"BotkitMessage\"\n                                            }\n                                          }\n                                        ],\n                                        \"type\": {\n                                          \"type\": \"reference\",\n                                          \"typeArguments\": [\n                                            {\n                                              \"type\": \"intrinsic\",\n                                              \"name\": \"boolean\"\n                                            }\n                                          ],\n                                          \"name\": \"Promise\"\n                                        }\n                                      }\n                                    ]\n                                  }\n                                }\n                              ]\n                            }\n                          },\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"RegExp\"\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          },\n                          {\n                            \"type\": \"reflection\",\n                            \"declaration\": {\n                              \"id\": 252,\n                              \"name\": \"__type\",\n                              \"kind\": 65536,\n                              \"kindString\": \"Type literal\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"signatures\": [\n                                {\n                                  \"id\": 253,\n                                  \"name\": \"__call\",\n                                  \"kind\": 4096,\n                                  \"kindString\": \"Call signature\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"parameters\": [\n                                    {\n                                      \"id\": 254,\n                                      \"name\": \"message\",\n                                      \"kind\": 32768,\n                                      \"kindString\": \"Parameter\",\n                                      \"flags\": {\n                                        \"isExported\": true\n                                      },\n                                      \"type\": {\n                                        \"type\": \"reference\",\n                                        \"id\": 152,\n                                        \"name\": \"BotkitMessage\"\n                                      }\n                                    }\n                                  ],\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"typeArguments\": [\n                                      {\n                                        \"type\": \"intrinsic\",\n                                        \"name\": \"boolean\"\n                                      }\n                                    ],\n                                    \"name\": \"Promise\"\n                                  }\n                                }\n                              ],\n                              \"sources\": [\n                                {\n                                  \"fileName\": \"core.ts\",\n                                  \"line\": 912,\n                                  \"character\": 115\n                                }\n                              ]\n                            }\n                          }\n                        ]\n                      }\n                    },\n                    {\n                      \"id\": 255,\n                      \"name\": \"events\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A list of event types that should be evaluated for the given patterns\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          },\n                          {\n                            \"type\": \"array\",\n                            \"elementType\": {\n                              \"type\": \"intrinsic\",\n                              \"name\": \"string\"\n                            }\n                          }\n                        ]\n                      }\n                    },\n                    {\n                      \"id\": 256,\n                      \"name\": \"handler\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"a function that will be called should the pattern be matched\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 162,\n                        \"name\": \"BotkitHandler\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 912,\n                  \"character\": 16\n                }\n              ]\n            },\n            {\n              \"id\": 257,\n              \"name\": \"interrupts\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 258,\n                  \"name\": \"interrupts\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Instruct your bot to listen for a pattern, and do something when that pattern is heard.\\nInterruptions work just like \\\"hears\\\" triggers, but fire _before_ the dialog system is engaged,\\nand thus handlers will interrupt the normal flow of messages through the processing pipeline.\",\n                    \"text\": \"```javascript\\ncontroller.interrupts('help','message', async(bot, message) => {\\n\\n await bot.reply(message,'Before anything else, you need some help!')\\n\\n});\\n```\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 259,\n                      \"name\": \"patterns\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"One or more string, regular expression, or test function\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"array\",\n                            \"elementType\": {\n                              \"type\": \"union\",\n                              \"types\": [\n                                {\n                                  \"type\": \"intrinsic\",\n                                  \"name\": \"string\"\n                                },\n                                {\n                                  \"type\": \"reference\",\n                                  \"name\": \"RegExp\"\n                                },\n                                {\n                                  \"type\": \"reflection\",\n                                  \"declaration\": {\n                                    \"id\": 260,\n                                    \"name\": \"__type\",\n                                    \"kind\": 65536,\n                                    \"kindString\": \"Type literal\",\n                                    \"flags\": {\n                                      \"isExported\": true\n                                    },\n                                    \"signatures\": [\n                                      {\n                                        \"id\": 261,\n                                        \"name\": \"__call\",\n                                        \"kind\": 4096,\n                                        \"kindString\": \"Call signature\",\n                                        \"flags\": {\n                                          \"isExported\": true\n                                        },\n                                        \"parameters\": [\n                                          {\n                                            \"id\": 262,\n                                            \"name\": \"message\",\n                                            \"kind\": 32768,\n                                            \"kindString\": \"Parameter\",\n                                            \"flags\": {\n                                              \"isExported\": true\n                                            },\n                                            \"type\": {\n                                              \"type\": \"reference\",\n                                              \"id\": 152,\n                                              \"name\": \"BotkitMessage\"\n                                            }\n                                          }\n                                        ],\n                                        \"type\": {\n                                          \"type\": \"reference\",\n                                          \"typeArguments\": [\n                                            {\n                                              \"type\": \"intrinsic\",\n                                              \"name\": \"boolean\"\n                                            }\n                                          ],\n                                          \"name\": \"Promise\"\n                                        }\n                                      }\n                                    ]\n                                  }\n                                }\n                              ]\n                            }\n                          },\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"RegExp\"\n                          },\n                          {\n                            \"type\": \"array\",\n                            \"elementType\": {\n                              \"type\": \"reference\",\n                              \"name\": \"RegExp\"\n                            }\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          },\n                          {\n                            \"type\": \"reflection\",\n                            \"declaration\": {\n                              \"id\": 263,\n                              \"name\": \"__type\",\n                              \"kind\": 65536,\n                              \"kindString\": \"Type literal\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"signatures\": [\n                                {\n                                  \"id\": 264,\n                                  \"name\": \"__call\",\n                                  \"kind\": 4096,\n                                  \"kindString\": \"Call signature\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"parameters\": [\n                                    {\n                                      \"id\": 265,\n                                      \"name\": \"message\",\n                                      \"kind\": 32768,\n                                      \"kindString\": \"Parameter\",\n                                      \"flags\": {\n                                        \"isExported\": true\n                                      },\n                                      \"type\": {\n                                        \"type\": \"reference\",\n                                        \"id\": 152,\n                                        \"name\": \"BotkitMessage\"\n                                      }\n                                    }\n                                  ],\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"typeArguments\": [\n                                      {\n                                        \"type\": \"intrinsic\",\n                                        \"name\": \"boolean\"\n                                      }\n                                    ],\n                                    \"name\": \"Promise\"\n                                  }\n                                }\n                              ],\n                              \"sources\": [\n                                {\n                                  \"fileName\": \"core.ts\",\n                                  \"line\": 967,\n                                  \"character\": 131\n                                }\n                              ]\n                            }\n                          }\n                        ]\n                      }\n                    },\n                    {\n                      \"id\": 266,\n                      \"name\": \"events\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A list of event types that should be evaluated for the given patterns\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          },\n                          {\n                            \"type\": \"array\",\n                            \"elementType\": {\n                              \"type\": \"intrinsic\",\n                              \"name\": \"string\"\n                            }\n                          }\n                        ]\n                      }\n                    },\n                    {\n                      \"id\": 267,\n                      \"name\": \"handler\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"a function that will be called should the pattern be matched\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 162,\n                        \"name\": \"BotkitHandler\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 967,\n                  \"character\": 21\n                }\n              ]\n            },\n            {\n              \"id\": 281,\n              \"name\": \"loadModule\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 282,\n                  \"name\": \"loadModule\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Load a Botkit feature module\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 283,\n                      \"name\": \"p\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"path to module file\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 1121,\n                  \"character\": 21\n                }\n              ]\n            },\n            {\n              \"id\": 284,\n              \"name\": \"loadModules\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 285,\n                  \"name\": \"loadModules\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Load all Botkit feature modules located in a given folder.\",\n                    \"text\": \"```javascript\\ncontroller.ready(() => {\\n\\n // load all modules from sub-folder features/\\n controller.loadModules('./features');\\n\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 286,\n                      \"name\": \"p\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"path to a folder of module files\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 287,\n                      \"name\": \"exts\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"the extensions that you would like to load (default: ['.js'])\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"intrinsic\",\n                          \"name\": \"string\"\n                        }\n                      },\n                      \"defaultValue\": \"['.js']\"\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 1150,\n                  \"character\": 22\n                }\n              ]\n            },\n            {\n              \"id\": 268,\n              \"name\": \"on\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 269,\n                  \"name\": \"on\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Bind a handler function to one or more events.\",\n                    \"text\": \"```javascript\\ncontroller.on('conversationUpdate', async(bot, message) => {\\n\\n await bot.reply(message,'I received a conversationUpdate event.');\\n\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 270,\n                      \"name\": \"events\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"One or more event names\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          },\n                          {\n                            \"type\": \"array\",\n                            \"elementType\": {\n                              \"type\": \"intrinsic\",\n                              \"name\": \"string\"\n                            }\n                          }\n                        ]\n                      }\n                    },\n                    {\n                      \"id\": 271,\n                      \"name\": \"handler\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"a handler function that will fire whenever one of the named events is received.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 162,\n                        \"name\": \"BotkitHandler\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 1019,\n                  \"character\": 13\n                }\n              ]\n            },\n            {\n              \"id\": 222,\n              \"name\": \"publicFolder\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 223,\n                  \"name\": \"publicFolder\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Expose a folder to the web as a set of static files.\\nUseful for plugins that need to bundle additional assets!\",\n                    \"text\": \"```javascript\\n// make content of the local public folder available at http://MYBOTURL/public/myplugin\\ncontroller.publicFolder('/public/myplugin', __dirname + '/public);\\n```\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 224,\n                      \"name\": \"alias\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"the public alias ie /myfiles\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 225,\n                      \"name\": \"path\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"the actual path something like `__dirname + '/public'`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 587,\n                  \"character\": 23\n                }\n              ]\n            },\n            {\n              \"id\": 235,\n              \"name\": \"ready\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 236,\n                  \"name\": \"ready\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Use `controller.ready()` to wrap any calls that require components loaded during the bootup process.\\nThis will ensure that the calls will not be made until all of the components have successfully been initialized.\",\n                    \"text\": \"For example:\\n```javascript\\ncontroller.ready(() => {\\n\\n  controller.loadModules(__dirname + '/features');\\n\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 237,\n                      \"name\": \"handler\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A function to run when Botkit is booted and ready to run.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 238,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 239,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"type\": {\n                                \"type\": \"intrinsic\",\n                                \"name\": \"any\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"core.ts\",\n                              \"line\": 676,\n                              \"character\": 25\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 676,\n                  \"character\": 16\n                }\n              ]\n            },\n            {\n              \"id\": 243,\n              \"name\": \"saveState\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 244,\n                  \"name\": \"saveState\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Save the current conversation state pertaining to a given BotWorker's activities.\\nNote: this is normally called internally and is only required when state changes happen outside of the normal processing flow.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 245,\n                      \"name\": \"bot\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"a BotWorker instance created using `controller.spawn()`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 2,\n                        \"name\": \"BotWorker\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 783,\n                  \"character\": 26\n                }\n              ]\n            },\n            {\n              \"id\": 202,\n              \"name\": \"shutdown\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 203,\n                  \"name\": \"shutdown\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Shutdown the webserver and prepare to terminate the app.\\nCauses Botkit to first emit a special `shutdown` event, process any bound handlers, and then finally terminate the webserver.\\nBind any necessary cleanup helpers to the shutdown event - for example, close the connection to mongo.\",\n                    \"text\": \"```javascript\\nawait controller.shutdown();\\ncontroller.on('shutdown', async() => {\\n     console.log('Bot is shutting down!');\\n});\\n```\\n\"\n                  },\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 453,\n                  \"character\": 25\n                }\n              ]\n            },\n            {\n              \"id\": 277,\n              \"name\": \"spawn\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 278,\n                  \"name\": \"spawn\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Create a platform-specific BotWorker instance that can be used to respond to messages or generate new outbound messages.\\nThe spawned `bot` contains all information required to process outbound messages and handle dialog state, and may also contain extensions\\nfor handling platform-specific events or activities.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 279,\n                      \"name\": \"config\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"Preferably receives a DialogContext, though can also receive a TurnContext. If excluded, must call `bot.changeContext(reference)` before calling any other method.\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 280,\n                      \"name\": \"custom_adapter\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"BotAdapter\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"reference\",\n                        \"id\": 2,\n                        \"name\": \"BotWorker\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 1075,\n                  \"character\": 22\n                }\n              ]\n            },\n            {\n              \"id\": 272,\n              \"name\": \"trigger\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 273,\n                  \"name\": \"trigger\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Trigger an event to be fired.  This will cause any bound handlers to be executed.\\nNote: This is normally used internally, but can be used to emit custom events.\",\n                    \"text\": \"```javascript\\n// fire a custom event\\ncontroller.trigger('my_custom_event', bot, message);\\n\\n// handle the custom event\\ncontroller.on('my_custom_event', async(bot, message) => {\\n //... do something\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 274,\n                      \"name\": \"event\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"the name of the event\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 275,\n                      \"name\": \"bot\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"a BotWorker instance created using `controller.spawn()`\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 2,\n                        \"name\": \"BotWorker\"\n                      }\n                    },\n                    {\n                      \"id\": 276,\n                      \"name\": \"message\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An incoming message or event\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 152,\n                        \"name\": \"BotkitMessage\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 1051,\n                  \"character\": 24\n                }\n              ]\n            },\n            {\n              \"id\": 207,\n              \"name\": \"usePlugin\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 208,\n                  \"name\": \"usePlugin\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Load a plugin module and bind all included middlewares to their respective endpoints.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 209,\n                      \"name\": \"plugin_or_function\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A plugin module in the form of function(botkit) {...} that returns {name, middlewares, init} or an object in the same form.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"reflection\",\n                            \"declaration\": {\n                              \"id\": 210,\n                              \"name\": \"__type\",\n                              \"kind\": 65536,\n                              \"kindString\": \"Type literal\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"signatures\": [\n                                {\n                                  \"id\": 211,\n                                  \"name\": \"__call\",\n                                  \"kind\": 4096,\n                                  \"kindString\": \"Call signature\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"parameters\": [\n                                    {\n                                      \"id\": 212,\n                                      \"name\": \"botkit\",\n                                      \"kind\": 32768,\n                                      \"kindString\": \"Parameter\",\n                                      \"flags\": {\n                                        \"isExported\": true\n                                      },\n                                      \"type\": {\n                                        \"type\": \"reference\",\n                                        \"id\": 185,\n                                        \"name\": \"Botkit\"\n                                      }\n                                    }\n                                  ],\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"id\": 173,\n                                    \"name\": \"BotkitPlugin\"\n                                  }\n                                }\n                              ],\n                              \"sources\": [\n                                {\n                                  \"fileName\": \"core.ts\",\n                                  \"line\": 489,\n                                  \"character\": 40\n                                }\n                              ]\n                            }\n                          },\n                          {\n                            \"type\": \"reference\",\n                            \"id\": 173,\n                            \"name\": \"BotkitPlugin\"\n                          }\n                        ]\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 489,\n                  \"character\": 20\n                }\n              ]\n            }\n          ],\n          \"constructors\": [\n            {\n              \"id\": 199,\n              \"name\": \"constructor\",\n              \"kind\": 512,\n              \"kindString\": \"Constructor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Create a new Botkit instance and optionally specify a platform-specific adapter.\\nBy default, Botkit will create a [BotFrameworkAdapter](https://docs.microsoft.com/en-us/javascript/api/botbuilder/botframeworkadapter?view=botbuilder-ts-latest).\",\n                \"text\": \"```javascript\\nconst controller = new Botkit({\\n     adapter: some_adapter,\\n     webhook_uri: '/api/messages',\\n});\\n\\ncontroller.on('message', async(bot, message) => {\\n     // do something!\\n});\\n```\\n\"\n              },\n              \"signatures\": [\n                {\n                  \"id\": 200,\n                  \"name\": \"new Botkit\",\n                  \"kind\": 16384,\n                  \"kindString\": \"Constructor signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Create a new Botkit instance and optionally specify a platform-specific adapter.\\nBy default, Botkit will create a [BotFrameworkAdapter](https://docs.microsoft.com/en-us/javascript/api/botbuilder/botframeworkadapter?view=botbuilder-ts-latest).\",\n                    \"text\": \"```javascript\\nconst controller = new Botkit({\\n     adapter: some_adapter,\\n     webhook_uri: '/api/messages',\\n});\\n\\ncontroller.on('message', async(bot, message) => {\\n     // do something!\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 201,\n                      \"name\": \"config\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"Configuration for this instance of Botkit\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 137,\n                        \"name\": \"BotkitConfiguration\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 185,\n                    \"name\": \"Botkit\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 310,\n                  \"character\": 28\n                }\n              ]\n            }\n          ]\n        },\n        {\n          \"id\": 114,\n          \"name\": \"BotkitBotFrameworkAdapter\",\n          \"kind\": 128,\n          \"kindString\": \"Class\",\n          \"flags\": {\n            \"isExported\": true,\n            \"isExternal\": true\n          },\n          \"comment\": {\n            \"shortText\": \"This class extends the [BotFrameworkAdapter](https://docs.microsoft.com/en-us/javascript/api/botbuilder/botframeworkadapter?view=botbuilder-ts-latest) with a few additional features to support Microsoft Teams.\\n* Changes userAgent to reflect Botkit instead of BotBuilder\\n* Adds getChannels() (MS Teams)\\n* Adds middleware for adjusting location of tenant id field (MS Teams)\"\n          },\n          \"children\": [\n            {\n              \"id\": 115,\n              \"name\": \"botkit_worker\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"adapter.ts\",\n                  \"line\": 30,\n                  \"character\": 24\n                }\n              ],\n              \"type\": {\n                \"type\": \"reference\",\n                \"id\": 52,\n                \"name\": \"TeamsBotWorker\"\n              },\n              \"defaultValue\": \"TeamsBotWorker\"\n            },\n            {\n              \"id\": 122,\n              \"name\": \"getChannels\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 123,\n                  \"name\": \"getChannels\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Get the list of channels in a MS Teams team.\\nCan only be called with a TurnContext that originated in a team conversation - 1:1 conversations happen _outside a team_ and thus do not contain the required information to call this API.\",\n                    \"returns\": \"an array of channels in the format [{name: string, id: string}]\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 124,\n                      \"name\": \"context\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A TurnContext object representing a message or event from a user in Teams\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"TurnContext\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"reference\",\n                          \"name\": \"ChannelInfo\"\n                        }\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"adapter.ts\",\n                  \"line\": 60,\n                  \"character\": 28\n                }\n              ]\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Properties\",\n              \"kind\": 1024,\n              \"children\": [\n                115\n              ]\n            },\n            {\n              \"title\": \"Methods\",\n              \"kind\": 2048,\n              \"children\": [\n                122\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"adapter.ts\",\n              \"line\": 29,\n              \"character\": 38\n            }\n          ],\n          \"extendedTypes\": [\n            {\n              \"type\": \"intrinsic\",\n              \"name\": \"any\"\n            }\n          ],\n          \"props\": [\n            {\n              \"id\": 115,\n              \"name\": \"botkit_worker\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"adapter.ts\",\n                  \"line\": 30,\n                  \"character\": 24\n                }\n              ],\n              \"type\": {\n                \"type\": \"reference\",\n                \"id\": 52,\n                \"name\": \"TeamsBotWorker\"\n              },\n              \"defaultValue\": \"TeamsBotWorker\"\n            }\n          ],\n          \"methods\": [\n            {\n              \"id\": 122,\n              \"name\": \"getChannels\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 123,\n                  \"name\": \"getChannels\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Get the list of channels in a MS Teams team.\\nCan only be called with a TurnContext that originated in a team conversation - 1:1 conversations happen _outside a team_ and thus do not contain the required information to call this API.\",\n                    \"returns\": \"an array of channels in the format [{name: string, id: string}]\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 124,\n                      \"name\": \"context\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A TurnContext object representing a message or event from a user in Teams\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"TurnContext\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"reference\",\n                          \"name\": \"ChannelInfo\"\n                        }\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"adapter.ts\",\n                  \"line\": 60,\n                  \"character\": 28\n                }\n              ]\n            }\n          ],\n          \"constructors\": []\n        },\n        {\n          \"id\": 52,\n          \"name\": \"TeamsBotWorker\",\n          \"kind\": 128,\n          \"kindString\": \"Class\",\n          \"flags\": {\n            \"isExported\": true,\n            \"isExternal\": true\n          },\n          \"comment\": {\n            \"shortText\": \"This is a specialized version of [Botkit's core BotWorker class](core.md#BotWorker) that includes additional methods for interacting with Microsoft Teams.\\nIt includes all functionality from the base class, as well as the extension methods below.\\nThis BotWorker is used with the built-in Bot Framework adapter.\"\n          },\n          \"children\": [\n            {\n              \"id\": 53,\n              \"name\": \"teams\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Grants access to the TeamsInfo helper class\\nSee: https://docs.microsoft.com/en-us/javascript/api/botbuilder/teamsinfo?view=botbuilder-ts-latest\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"teamsHelpers.ts\",\n                  \"line\": 23,\n                  \"character\": 14\n                }\n              ],\n              \"type\": {\n                \"type\": \"reference\",\n                \"name\": \"TeamsInfo\"\n              },\n              \"defaultValue\": \"TeamsInfo\"\n            },\n            {\n              \"id\": 54,\n              \"name\": \"replyWithTaskInfo\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 55,\n                  \"name\": \"replyWithTaskInfo\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Reply to a Teams task module task/fetch or task/submit with a task module response.\\nSee https://docs.microsoft.com/en-us/microsoftteams/platform/task-modules-and-cards/task-modules/task-modules-bots\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 56,\n                      \"name\": \"message\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 152,\n                        \"name\": \"BotkitMessage\"\n                      }\n                    },\n                    {\n                      \"id\": 57,\n                      \"name\": \"taskInfo\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"an object in the form {type, value}\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"teamsHelpers.ts\",\n                  \"line\": 31,\n                  \"character\": 32\n                }\n              ]\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Properties\",\n              \"kind\": 1024,\n              \"children\": [\n                53\n              ]\n            },\n            {\n              \"title\": \"Methods\",\n              \"kind\": 2048,\n              \"children\": [\n                54\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"teamsHelpers.ts\",\n              \"line\": 18,\n              \"character\": 27\n            }\n          ],\n          \"extendedTypes\": [\n            {\n              \"type\": \"reference\",\n              \"id\": 2,\n              \"name\": \"BotWorker\"\n            }\n          ],\n          \"props\": [\n            {\n              \"id\": 53,\n              \"name\": \"teams\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Grants access to the TeamsInfo helper class\\nSee: https://docs.microsoft.com/en-us/javascript/api/botbuilder/teamsinfo?view=botbuilder-ts-latest\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"teamsHelpers.ts\",\n                  \"line\": 23,\n                  \"character\": 14\n                }\n              ],\n              \"type\": {\n                \"type\": \"reference\",\n                \"name\": \"TeamsInfo\"\n              },\n              \"defaultValue\": \"TeamsInfo\"\n            }\n          ],\n          \"methods\": [\n            {\n              \"id\": 54,\n              \"name\": \"replyWithTaskInfo\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 55,\n                  \"name\": \"replyWithTaskInfo\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Reply to a Teams task module task/fetch or task/submit with a task module response.\\nSee https://docs.microsoft.com/en-us/microsoftteams/platform/task-modules-and-cards/task-modules/task-modules-bots\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 56,\n                      \"name\": \"message\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 152,\n                        \"name\": \"BotkitMessage\"\n                      }\n                    },\n                    {\n                      \"id\": 57,\n                      \"name\": \"taskInfo\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"an object in the form {type, value}\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"teamsHelpers.ts\",\n                  \"line\": 31,\n                  \"character\": 32\n                }\n              ]\n            }\n          ],\n          \"constructors\": []\n        },\n        {\n          \"id\": 2,\n          \"name\": \"BotWorker\",\n          \"kind\": 128,\n          \"kindString\": \"Class\",\n          \"flags\": {\n            \"isExported\": true,\n            \"isExternal\": true\n          },\n          \"comment\": {\n            \"shortText\": \"A base class for a `bot` instance, an object that contains the information and functionality for taking action in response to an incoming message.\\nNote that adapters are likely to extend this class with additional platform-specific methods - refer to the adapter documentation for these extensions.\"\n          },\n          \"children\": [\n            {\n              \"id\": 3,\n              \"name\": \"constructor\",\n              \"kind\": 512,\n              \"kindString\": \"Constructor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Create a new BotWorker instance. Do not call this directly - instead, use [controller.spawn()](#spawn).\"\n              },\n              \"signatures\": [\n                {\n                  \"id\": 4,\n                  \"name\": \"new BotWorker\",\n                  \"kind\": 16384,\n                  \"kindString\": \"Constructor signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Create a new BotWorker instance. Do not call this directly - instead, use [controller.spawn()](#spawn).\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 5,\n                      \"name\": \"controller\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"A pointer to the main Botkit controller\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 185,\n                        \"name\": \"Botkit\"\n                      }\n                    },\n                    {\n                      \"id\": 6,\n                      \"name\": \"config\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"An object typically containing { dialogContext, reference, context, activity }\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 2,\n                    \"name\": \"BotWorker\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 18,\n                  \"character\": 25\n                }\n              ]\n            },\n            {\n              \"id\": 7,\n              \"name\": \"controller\",\n              \"kind\": 262144,\n              \"kindString\": \"Accessor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Get a reference to the main Botkit controller.\"\n              },\n              \"getSignature\": [\n                {\n                  \"id\": 8,\n                  \"name\": \"__get\",\n                  \"kind\": 524288,\n                  \"kindString\": \"Get signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Get a reference to the main Botkit controller.\"\n                  },\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 185,\n                    \"name\": \"Botkit\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 35,\n                  \"character\": 25\n                }\n              ]\n            },\n            {\n              \"id\": 19,\n              \"name\": \"beginDialog\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 20,\n                  \"name\": \"beginDialog\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Begin a pre-defined dialog by specifying its id. The dialog will be started in the same context (same user, same channel) in which the original incoming message was received.\\n[See \\\"Using Dialogs\\\" in the core documentation.](../index.md#using-dialogs)\",\n                    \"text\": \"```javascript\\ncontroller.hears('hello', 'message', async(bot, message) => {\\n     await bot.beginDialog(GREETINGS_DIALOG);\\n});\\n```\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 21,\n                      \"name\": \"id\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"id of dialog\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 22,\n                      \"name\": \"options\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"object containing options to be passed into the dialog\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 153,\n                  \"character\": 28\n                }\n              ]\n            },\n            {\n              \"id\": 23,\n              \"name\": \"cancelAllDialogs\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 24,\n                  \"name\": \"cancelAllDialogs\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Cancel any and all active dialogs for the current user/context.\"\n                  },\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"reference\",\n                        \"name\": \"DialogTurnResult\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 172,\n                  \"character\": 33\n                }\n              ]\n            },\n            {\n              \"id\": 36,\n              \"name\": \"changeContext\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 37,\n                  \"name\": \"changeContext\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Alter the context in which a bot instance will send messages.\\nUse this method to create or adjust a bot instance so that it can send messages to a predefined user/channel combination.\",\n                    \"text\": \"```javascript\\n// get the reference field and store it.\\nconst saved_reference = message.reference;\\n\\n// later on...\\nlet bot = await controller.spawn();\\nbot.changeContext(saved_reference);\\nbot.say('Hello!');\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 38,\n                      \"name\": \"reference\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A [ConversationReference](https://docs.microsoft.com/en-us/javascript/api/botframework-schema/conversationreference?view=botbuilder-ts-latest), most likely captured from an incoming message and stored for use in proactive messaging scenarios.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"ConversationReference\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"reference\",\n                        \"id\": 2,\n                        \"name\": \"BotWorker\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 250,\n                  \"character\": 30\n                }\n              ]\n            },\n            {\n              \"id\": 42,\n              \"name\": \"ensureMessageFormat\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 43,\n                  \"name\": \"ensureMessageFormat\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Take a crudely-formed Botkit message with any sort of field (may just be a string, may be a partial message object)\\nand map it into a beautiful BotFramework Activity.\\nAny fields not found in the Activity definition will be moved to activity.channelData.\",\n                    \"returns\": \"a properly formed Activity object\\n\",\n                    \"tags\": [\n                      {\n                        \"tag\": \"params\",\n                        \"text\": \"message a string or partial outgoing message object\"\n                      }\n                    ]\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 44,\n                      \"name\": \"message\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"reference\",\n                            \"typeArguments\": [\n                              {\n                                \"type\": \"reference\",\n                                \"id\": 152,\n                                \"name\": \"BotkitMessage\"\n                              }\n                            ],\n                            \"name\": \"Partial\"\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        ]\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"reference\",\n                        \"name\": \"Activity\"\n                      }\n                    ],\n                    \"name\": \"Partial\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 332,\n                  \"character\": 30\n                }\n              ]\n            },\n            {\n              \"id\": 25,\n              \"name\": \"getActiveDialog\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 26,\n                  \"name\": \"getActiveDialog\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Get a reference to the active dialog\",\n                    \"returns\": \"a reference to the active dialog or undefined if no dialog is active\\n\"\n                  },\n                  \"type\": {\n                    \"type\": \"union\",\n                    \"types\": [\n                      {\n                        \"type\": \"reference\",\n                        \"name\": \"Dialog\"\n                      },\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"undefined\"\n                      }\n                    ]\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 182,\n                  \"character\": 26\n                }\n              ]\n            },\n            {\n              \"id\": 9,\n              \"name\": \"getConfig\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 10,\n                  \"name\": \"getConfig\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Get a value from the BotWorker's configuration.\",\n                    \"text\": \"```javascript\\nlet original_context = bot.getConfig('context');\\nawait original_context.sendActivity('send directly using the adapter instead of Botkit');\\n```\\n\",\n                    \"returns\": \"The value stored in the configuration (or null if absent)\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 11,\n                      \"name\": \"key\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"The name of a value stored in the configuration\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"any\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 50,\n                  \"character\": 20\n                }\n              ]\n            },\n            {\n              \"id\": 27,\n              \"name\": \"hasActiveDialog\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 28,\n                  \"name\": \"hasActiveDialog\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Check if any dialog is active or not\",\n                    \"returns\": \"true if there is an active dialog, otherwise false\\n\"\n                  },\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"boolean\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 190,\n                  \"character\": 26\n                }\n              ]\n            },\n            {\n              \"id\": 48,\n              \"name\": \"httpBody\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 49,\n                  \"name\": \"httpBody\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Set the http response body for this turn.\\nUse this to define the response value when the platform requires a synchronous response to the incoming webhook.\",\n                    \"text\": \"Example handling of a /slash command from Slack:\\n```javascript\\ncontroller.on('slash_command', async(bot, message) => {\\n bot.httpBody('This is a reply to the slash command.');\\n})\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 50,\n                      \"name\": \"body\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"(any) a value that will be returned as the http response body\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 432,\n                  \"character\": 19\n                }\n              ]\n            },\n            {\n              \"id\": 45,\n              \"name\": \"httpStatus\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 46,\n                  \"name\": \"httpStatus\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Set the http response status code for this turn\",\n                    \"text\": \"```javascript\\ncontroller.on('event', async(bot, message) => {\\n  // respond with a 500 error code for some reason!\\n  bot.httpStatus(500);\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 47,\n                      \"name\": \"status\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"a valid http status code like 200 202 301 500 etc\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"number\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 415,\n                  \"character\": 21\n                }\n              ]\n            },\n            {\n              \"id\": 29,\n              \"name\": \"isDialogActive\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 30,\n                  \"name\": \"isDialogActive\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Check to see if a given dialog is currently active in the stack\",\n                    \"returns\": \"true if dialog with id is located anywhere in the dialog stack\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 31,\n                      \"name\": \"id\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"The id of a dialog to look for in the dialog stack\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"boolean\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 199,\n                  \"character\": 25\n                }\n              ]\n            },\n            {\n              \"id\": 32,\n              \"name\": \"replaceDialog\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 33,\n                  \"name\": \"replaceDialog\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Replace any active dialogs with a new a pre-defined dialog by specifying its id. The dialog will be started in the same context (same user, same channel) in which the original incoming message was received.\\n[See \\\"Using Dialogs\\\" in the core documentation.](../index.md#using-dialogs)\",\n                    \"text\": \"```javascript\\ncontroller.hears('hello', 'message', async(bot, message) => {\\n     await bot.replaceDialog(GREETINGS_DIALOG);\\n});\\n```\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 34,\n                      \"name\": \"id\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"id of dialog\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 35,\n                      \"name\": \"options\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"object containing options to be passed into the dialog\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 218,\n                  \"character\": 30\n                }\n              ]\n            },\n            {\n              \"id\": 15,\n              \"name\": \"reply\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 16,\n                  \"name\": \"reply\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Reply to an incoming message.\\nMessage will be sent using the context of the source message, which may in some cases be different than the context used to spawn the bot.\",\n                    \"text\": \"Note that like [bot.say()](#say), `reply()` can take a string or a message object.\\n\\n```javascript\\ncontroller.on('event', async(bot, message) => {\\n\\n await bot.reply(message, 'I received an event and am replying to it.');\\n\\n});\\n```\\n\",\n                    \"returns\": \"Return value will contain the results of the send action, typically `{id: <id of message>}`\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 17,\n                      \"name\": \"src\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An incoming message, usually passed in to a handler function\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"id\": 152,\n                            \"name\": \"BotkitMessage\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    },\n                    {\n                      \"id\": 18,\n                      \"name\": \"resp\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A string containing the text of a reply, or more fully formed message object\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"reference\",\n                            \"typeArguments\": [\n                              {\n                                \"type\": \"reference\",\n                                \"id\": 152,\n                                \"name\": \"BotkitMessage\"\n                              }\n                            ],\n                            \"name\": \"Partial\"\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        ]\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 130,\n                  \"character\": 22\n                }\n              ]\n            },\n            {\n              \"id\": 12,\n              \"name\": \"say\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 13,\n                  \"name\": \"say\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Send a message using whatever context the `bot` was spawned in or set using [changeContext()](#changecontext) --\\nor more likely, one of the platform-specific helpers like\\n[startPrivateConversation()](../reference/slack.md#startprivateconversation) (Slack),\\n[startConversationWithUser()](../reference/twilio-sms.md#startconversationwithuser) (Twilio SMS),\\nand [startConversationWithUser()](../reference/facebook.md#startconversationwithuser) (Facebook Messenger).\\nBe sure to check the platform documentation for others - most adapters include at least one.\",\n                    \"text\": \"Simple use in event handler (acts the same as bot.reply)\\n```javascript\\ncontroller.on('event', async(bot, message) => {\\n\\n await bot.say('I received an event!');\\n\\n});\\n```\\n\\nUse with a freshly spawned bot and bot.changeContext:\\n```javascript\\nlet bot = controller.spawn(OPTIONS);\\nbot.changeContext(REFERENCE);\\nbot.say('ALERT! I have some news.');\\n```\\n\\nUse with multi-field message object:\\n```javascript\\ncontroller.on('event', async(bot, message) => {\\n     bot.say({\\n         text: 'I heard an event',\\n         attachments: [\\n             title: message.type,\\n             text: `The message was of type ${ message.type }`,\\n             // ...\\n         ]\\n     });\\n});\\n```\\n\",\n                    \"returns\": \"Return value will contain the results of the send action, typically `{id: <id of message>}`\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 14,\n                      \"name\": \"message\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A string containing the text of a reply, or more fully formed message object\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"reference\",\n                            \"typeArguments\": [\n                              {\n                                \"type\": \"reference\",\n                                \"id\": 152,\n                                \"name\": \"BotkitMessage\"\n                              }\n                            ],\n                            \"name\": \"Partial\"\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        ]\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 99,\n                  \"character\": 20\n                }\n              ]\n            },\n            {\n              \"id\": 39,\n              \"name\": \"startConversationWithUser\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 40,\n                  \"name\": \"startConversationWithUser\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 41,\n                      \"name\": \"reference\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 274,\n                  \"character\": 42\n                }\n              ]\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Constructors\",\n              \"kind\": 512,\n              \"children\": [\n                3\n              ]\n            },\n            {\n              \"title\": \"Accessors\",\n              \"kind\": 262144,\n              \"children\": [\n                7\n              ]\n            },\n            {\n              \"title\": \"Methods\",\n              \"kind\": 2048,\n              \"children\": [\n                19,\n                23,\n                36,\n                42,\n                25,\n                9,\n                27,\n                48,\n                45,\n                29,\n                32,\n                15,\n                12,\n                39\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"botworker.ts\",\n              \"line\": 16,\n              \"character\": 22\n            }\n          ],\n          \"extendedBy\": [\n            {\n              \"type\": \"reference\",\n              \"id\": 52,\n              \"name\": \"TeamsBotWorker\"\n            }\n          ],\n          \"props\": [\n            {\n              \"id\": 7,\n              \"name\": \"controller\",\n              \"kind\": 262144,\n              \"kindString\": \"Accessor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Get a reference to the main Botkit controller.\"\n              },\n              \"getSignature\": [\n                {\n                  \"id\": 8,\n                  \"name\": \"__get\",\n                  \"kind\": 524288,\n                  \"kindString\": \"Get signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Get a reference to the main Botkit controller.\"\n                  },\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 185,\n                    \"name\": \"Botkit\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 35,\n                  \"character\": 25\n                }\n              ]\n            }\n          ],\n          \"methods\": [\n            {\n              \"id\": 19,\n              \"name\": \"beginDialog\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 20,\n                  \"name\": \"beginDialog\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Begin a pre-defined dialog by specifying its id. The dialog will be started in the same context (same user, same channel) in which the original incoming message was received.\\n[See \\\"Using Dialogs\\\" in the core documentation.](../index.md#using-dialogs)\",\n                    \"text\": \"```javascript\\ncontroller.hears('hello', 'message', async(bot, message) => {\\n     await bot.beginDialog(GREETINGS_DIALOG);\\n});\\n```\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 21,\n                      \"name\": \"id\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"id of dialog\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 22,\n                      \"name\": \"options\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"object containing options to be passed into the dialog\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 153,\n                  \"character\": 28\n                }\n              ]\n            },\n            {\n              \"id\": 23,\n              \"name\": \"cancelAllDialogs\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 24,\n                  \"name\": \"cancelAllDialogs\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Cancel any and all active dialogs for the current user/context.\"\n                  },\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"reference\",\n                        \"name\": \"DialogTurnResult\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 172,\n                  \"character\": 33\n                }\n              ]\n            },\n            {\n              \"id\": 36,\n              \"name\": \"changeContext\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 37,\n                  \"name\": \"changeContext\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Alter the context in which a bot instance will send messages.\\nUse this method to create or adjust a bot instance so that it can send messages to a predefined user/channel combination.\",\n                    \"text\": \"```javascript\\n// get the reference field and store it.\\nconst saved_reference = message.reference;\\n\\n// later on...\\nlet bot = await controller.spawn();\\nbot.changeContext(saved_reference);\\nbot.say('Hello!');\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 38,\n                      \"name\": \"reference\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A [ConversationReference](https://docs.microsoft.com/en-us/javascript/api/botframework-schema/conversationreference?view=botbuilder-ts-latest), most likely captured from an incoming message and stored for use in proactive messaging scenarios.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"ConversationReference\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"reference\",\n                        \"id\": 2,\n                        \"name\": \"BotWorker\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 250,\n                  \"character\": 30\n                }\n              ]\n            },\n            {\n              \"id\": 42,\n              \"name\": \"ensureMessageFormat\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 43,\n                  \"name\": \"ensureMessageFormat\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Take a crudely-formed Botkit message with any sort of field (may just be a string, may be a partial message object)\\nand map it into a beautiful BotFramework Activity.\\nAny fields not found in the Activity definition will be moved to activity.channelData.\",\n                    \"returns\": \"a properly formed Activity object\\n\",\n                    \"tags\": [\n                      {\n                        \"tag\": \"params\",\n                        \"text\": \"message a string or partial outgoing message object\"\n                      }\n                    ]\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 44,\n                      \"name\": \"message\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"reference\",\n                            \"typeArguments\": [\n                              {\n                                \"type\": \"reference\",\n                                \"id\": 152,\n                                \"name\": \"BotkitMessage\"\n                              }\n                            ],\n                            \"name\": \"Partial\"\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        ]\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"reference\",\n                        \"name\": \"Activity\"\n                      }\n                    ],\n                    \"name\": \"Partial\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 332,\n                  \"character\": 30\n                }\n              ]\n            },\n            {\n              \"id\": 25,\n              \"name\": \"getActiveDialog\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 26,\n                  \"name\": \"getActiveDialog\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Get a reference to the active dialog\",\n                    \"returns\": \"a reference to the active dialog or undefined if no dialog is active\\n\"\n                  },\n                  \"type\": {\n                    \"type\": \"union\",\n                    \"types\": [\n                      {\n                        \"type\": \"reference\",\n                        \"name\": \"Dialog\"\n                      },\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"undefined\"\n                      }\n                    ]\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 182,\n                  \"character\": 26\n                }\n              ]\n            },\n            {\n              \"id\": 9,\n              \"name\": \"getConfig\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 10,\n                  \"name\": \"getConfig\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Get a value from the BotWorker's configuration.\",\n                    \"text\": \"```javascript\\nlet original_context = bot.getConfig('context');\\nawait original_context.sendActivity('send directly using the adapter instead of Botkit');\\n```\\n\",\n                    \"returns\": \"The value stored in the configuration (or null if absent)\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 11,\n                      \"name\": \"key\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"The name of a value stored in the configuration\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"any\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 50,\n                  \"character\": 20\n                }\n              ]\n            },\n            {\n              \"id\": 27,\n              \"name\": \"hasActiveDialog\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 28,\n                  \"name\": \"hasActiveDialog\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Check if any dialog is active or not\",\n                    \"returns\": \"true if there is an active dialog, otherwise false\\n\"\n                  },\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"boolean\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 190,\n                  \"character\": 26\n                }\n              ]\n            },\n            {\n              \"id\": 48,\n              \"name\": \"httpBody\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 49,\n                  \"name\": \"httpBody\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Set the http response body for this turn.\\nUse this to define the response value when the platform requires a synchronous response to the incoming webhook.\",\n                    \"text\": \"Example handling of a /slash command from Slack:\\n```javascript\\ncontroller.on('slash_command', async(bot, message) => {\\n bot.httpBody('This is a reply to the slash command.');\\n})\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 50,\n                      \"name\": \"body\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"(any) a value that will be returned as the http response body\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 432,\n                  \"character\": 19\n                }\n              ]\n            },\n            {\n              \"id\": 45,\n              \"name\": \"httpStatus\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 46,\n                  \"name\": \"httpStatus\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Set the http response status code for this turn\",\n                    \"text\": \"```javascript\\ncontroller.on('event', async(bot, message) => {\\n  // respond with a 500 error code for some reason!\\n  bot.httpStatus(500);\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 47,\n                      \"name\": \"status\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"a valid http status code like 200 202 301 500 etc\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"number\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 415,\n                  \"character\": 21\n                }\n              ]\n            },\n            {\n              \"id\": 29,\n              \"name\": \"isDialogActive\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 30,\n                  \"name\": \"isDialogActive\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Check to see if a given dialog is currently active in the stack\",\n                    \"returns\": \"true if dialog with id is located anywhere in the dialog stack\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 31,\n                      \"name\": \"id\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"The id of a dialog to look for in the dialog stack\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"boolean\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 199,\n                  \"character\": 25\n                }\n              ]\n            },\n            {\n              \"id\": 32,\n              \"name\": \"replaceDialog\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 33,\n                  \"name\": \"replaceDialog\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Replace any active dialogs with a new a pre-defined dialog by specifying its id. The dialog will be started in the same context (same user, same channel) in which the original incoming message was received.\\n[See \\\"Using Dialogs\\\" in the core documentation.](../index.md#using-dialogs)\",\n                    \"text\": \"```javascript\\ncontroller.hears('hello', 'message', async(bot, message) => {\\n     await bot.replaceDialog(GREETINGS_DIALOG);\\n});\\n```\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 34,\n                      \"name\": \"id\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"id of dialog\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 35,\n                      \"name\": \"options\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"object containing options to be passed into the dialog\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 218,\n                  \"character\": 30\n                }\n              ]\n            },\n            {\n              \"id\": 15,\n              \"name\": \"reply\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 16,\n                  \"name\": \"reply\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Reply to an incoming message.\\nMessage will be sent using the context of the source message, which may in some cases be different than the context used to spawn the bot.\",\n                    \"text\": \"Note that like [bot.say()](#say), `reply()` can take a string or a message object.\\n\\n```javascript\\ncontroller.on('event', async(bot, message) => {\\n\\n await bot.reply(message, 'I received an event and am replying to it.');\\n\\n});\\n```\\n\",\n                    \"returns\": \"Return value will contain the results of the send action, typically `{id: <id of message>}`\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 17,\n                      \"name\": \"src\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An incoming message, usually passed in to a handler function\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"id\": 152,\n                            \"name\": \"BotkitMessage\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    },\n                    {\n                      \"id\": 18,\n                      \"name\": \"resp\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A string containing the text of a reply, or more fully formed message object\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"reference\",\n                            \"typeArguments\": [\n                              {\n                                \"type\": \"reference\",\n                                \"id\": 152,\n                                \"name\": \"BotkitMessage\"\n                              }\n                            ],\n                            \"name\": \"Partial\"\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        ]\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 130,\n                  \"character\": 22\n                }\n              ]\n            },\n            {\n              \"id\": 12,\n              \"name\": \"say\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 13,\n                  \"name\": \"say\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Send a message using whatever context the `bot` was spawned in or set using [changeContext()](#changecontext) --\\nor more likely, one of the platform-specific helpers like\\n[startPrivateConversation()](../reference/slack.md#startprivateconversation) (Slack),\\n[startConversationWithUser()](../reference/twilio-sms.md#startconversationwithuser) (Twilio SMS),\\nand [startConversationWithUser()](../reference/facebook.md#startconversationwithuser) (Facebook Messenger).\\nBe sure to check the platform documentation for others - most adapters include at least one.\",\n                    \"text\": \"Simple use in event handler (acts the same as bot.reply)\\n```javascript\\ncontroller.on('event', async(bot, message) => {\\n\\n await bot.say('I received an event!');\\n\\n});\\n```\\n\\nUse with a freshly spawned bot and bot.changeContext:\\n```javascript\\nlet bot = controller.spawn(OPTIONS);\\nbot.changeContext(REFERENCE);\\nbot.say('ALERT! I have some news.');\\n```\\n\\nUse with multi-field message object:\\n```javascript\\ncontroller.on('event', async(bot, message) => {\\n     bot.say({\\n         text: 'I heard an event',\\n         attachments: [\\n             title: message.type,\\n             text: `The message was of type ${ message.type }`,\\n             // ...\\n         ]\\n     });\\n});\\n```\\n\",\n                    \"returns\": \"Return value will contain the results of the send action, typically `{id: <id of message>}`\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 14,\n                      \"name\": \"message\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A string containing the text of a reply, or more fully formed message object\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"reference\",\n                            \"typeArguments\": [\n                              {\n                                \"type\": \"reference\",\n                                \"id\": 152,\n                                \"name\": \"BotkitMessage\"\n                              }\n                            ],\n                            \"name\": \"Partial\"\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        ]\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 99,\n                  \"character\": 20\n                }\n              ]\n            },\n            {\n              \"id\": 39,\n              \"name\": \"startConversationWithUser\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 40,\n                  \"name\": \"startConversationWithUser\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 41,\n                      \"name\": \"reference\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 274,\n                  \"character\": 42\n                }\n              ]\n            }\n          ],\n          \"constructors\": [\n            {\n              \"id\": 3,\n              \"name\": \"constructor\",\n              \"kind\": 512,\n              \"kindString\": \"Constructor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Create a new BotWorker instance. Do not call this directly - instead, use [controller.spawn()](#spawn).\"\n              },\n              \"signatures\": [\n                {\n                  \"id\": 4,\n                  \"name\": \"new BotWorker\",\n                  \"kind\": 16384,\n                  \"kindString\": \"Constructor signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Create a new BotWorker instance. Do not call this directly - instead, use [controller.spawn()](#spawn).\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 5,\n                      \"name\": \"controller\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"A pointer to the main Botkit controller\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 185,\n                        \"name\": \"Botkit\"\n                      }\n                    },\n                    {\n                      \"id\": 6,\n                      \"name\": \"config\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"An object typically containing { dialogContext, reference, context, activity }\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 2,\n                    \"name\": \"BotWorker\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 18,\n                  \"character\": 25\n                }\n              ]\n            }\n          ]\n        },\n        {\n          \"id\": 379,\n          \"name\": \"BotkitConversation\",\n          \"kind\": 128,\n          \"kindString\": \"Class\",\n          \"flags\": {\n            \"isExported\": true,\n            \"isExternal\": true\n          },\n          \"comment\": {\n            \"shortText\": \"An extension on the [BotBuilder Dialog Class](https://docs.microsoft.com/en-us/javascript/api/botbuilder-dialogs/dialog?view=botbuilder-ts-latest) that provides a Botkit-friendly interface for\\ndefining and interacting with multi-message dialogs. Dialogs can be constructed using `say()`, `ask()` and other helper methods.\",\n            \"text\": \"```javascript\\n// define the structure of your dialog...\\nconst convo = new BotkitConversation('foo', controller);\\nconvo.say('Hello!');\\nconvo.ask('What is your name?', async(answer, convo, bot) => {\\n     await bot.say('Your name is ' + answer);\\n});\\ncontroller.dialogSet.add(convo);\\n\\n// later on, trigger this dialog by its id\\ncontroller.on('event', async(bot, message) => {\\n await bot.beginDialog('foo');\\n})\\n```\\n\"\n          },\n          \"typeParameter\": [\n            {\n              \"id\": 380,\n              \"name\": \"O\",\n              \"kind\": 131072,\n              \"kindString\": \"Type parameter\",\n              \"flags\": {\n                \"isExported\": true\n              },\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"object\"\n              }\n            }\n          ],\n          \"children\": [\n            {\n              \"id\": 382,\n              \"name\": \"constructor\",\n              \"kind\": 512,\n              \"kindString\": \"Constructor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Create a new BotkitConversation object\"\n              },\n              \"signatures\": [\n                {\n                  \"id\": 383,\n                  \"name\": \"new BotkitConversation\",\n                  \"kind\": 16384,\n                  \"kindString\": \"Constructor signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Create a new BotkitConversation object\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 384,\n                      \"name\": \"dialogId\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"A unique identifier for this dialog, used to later trigger this dialog\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 385,\n                      \"name\": \"controller\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"A pointer to the main Botkit controller\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 185,\n                        \"name\": \"Botkit\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 379,\n                    \"name\": \"BotkitConversation\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 125,\n                  \"character\": 32\n                }\n              ]\n            },\n            {\n              \"id\": 381,\n              \"name\": \"script\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A map of every message in the dialog, broken into threads\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 119,\n                  \"character\": 17\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"any\"\n              }\n            },\n            {\n              \"id\": 389,\n              \"name\": \"addAction\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 390,\n                  \"name\": \"addAction\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"An an action to the conversation timeline. This can be used to go to switch threads or end the dialog.\",\n                    \"text\": \"When provided the name of another thread in the conversation, this will cause the bot to go immediately\\nto that thread.\\n\\nOtherwise, use one of the following keywords:\\n* `stop`\\n* `repeat`\\n* `complete`\\n* `timeout`\\n\\n[Learn more about building conversations &rarr;](../conversations.md#build-a-conversation)\\n\\n```javascript\\n\\n// go to a thread called \\\"next_thread\\\"\\nconvo.addAction('next_thread');\\n\\n// end the conversation and mark as successful\\nconvo.addAction('complete');\\n```\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 391,\n                      \"name\": \"action\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An action or thread name\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 392,\n                      \"name\": \"thread_name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"The name of the thread to which this action is added.  Defaults to `default`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      },\n                      \"defaultValue\": \"\\\"default\\\"\"\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 379,\n                    \"name\": \"BotkitConversation\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 197,\n                  \"character\": 20\n                }\n              ]\n            },\n            {\n              \"id\": 393,\n              \"name\": \"addChildDialog\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 394,\n                  \"name\": \"addChildDialog\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Cause the dialog to call a child dialog, wait for it to complete,\\nthen store the results in a variable and resume the parent dialog.\\nUse this to [combine multiple dialogs into bigger interactions.](../conversations.md#composing-dialogs)\",\n                    \"text\": \"[Learn more about building conversations &rarr;](../conversations.md#build-a-conversation)\\n```javascript\\n// define a profile collection dialog\\nlet profileDialog = new BotkitConversation('PROFILE_DIALOG', controller);\\nprofileDialog.ask('What is your name?', async(res, convo, bot) => {}, {key: 'name'});\\nprofileDialog.ask('What is your age?', async(res, convo, bot) => {}, {key: 'age'});\\nprofileDialog.ask('What is your location?', async(res, convo, bot) => {}, {key: 'location'});\\ncontroller.addDialog(profileDialog);\\n\\nlet onboard = new BotkitConversation('ONBOARDING', controller);\\nonboard.say('Hello! It is time to collect your profile data.');\\nonboard.addChildDialog('PROFILE_DIALOG', 'profile');\\nonboard.say('Hello, {{vars.profile.name}}! Onboarding is complete.');\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 395,\n                      \"name\": \"dialog_id\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"the id of another dialog\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 396,\n                      \"name\": \"key_name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"the variable name in which to store the results of the child dialog. if not provided, defaults to dialog_id.\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 397,\n                      \"name\": \"thread_name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"the name of a thread to which this call should be added. defaults to 'default'\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      },\n                      \"defaultValue\": \"\\\"default\\\"\"\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 379,\n                    \"name\": \"BotkitConversation\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 226,\n                  \"character\": 25\n                }\n              ]\n            },\n            {\n              \"id\": 398,\n              \"name\": \"addGotoDialog\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 399,\n                  \"name\": \"addGotoDialog\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Cause the current dialog to handoff to another dialog.\\nThe parent dialog will not resume when the child dialog completes. However, the afterDialog event will not fire for the parent dialog until all child dialogs complete.\\nUse this to [combine multiple dialogs into bigger interactions.](../conversations.md#composing-dialogs)\",\n                    \"text\": \"[Learn more about building conversations &rarr;](../conversations.md#build-a-conversation)\\n```javascript\\nlet parent = new BotkitConversation('parent', controller);\\nlet child = new BotkitConversation('child', controller);\\nparent.say('Moving on....');\\nparent.addGotoDialog('child');\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 400,\n                      \"name\": \"dialog_id\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"the id of another dialog\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 401,\n                      \"name\": \"thread_name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"the name of a thread to which this call should be added. defaults to 'default'\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      },\n                      \"defaultValue\": \"\\\"default\\\"\"\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 379,\n                    \"name\": \"BotkitConversation\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 253,\n                  \"character\": 24\n                }\n              ]\n            },\n            {\n              \"id\": 402,\n              \"name\": \"addMessage\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 403,\n                  \"name\": \"addMessage\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Add a message template to a specific thread.\\nMessages added with `say()` and `addMessage()` will be sent one after another without a pause.\",\n                    \"text\": \"[Learn more about building conversations &rarr;](../conversations.md#build-a-conversation)\\n```javascript\\nlet conversation = new BotkitConversation('welcome', controller);\\nconversation.say('Hello! Welcome to my app.');\\nconversation.say('Let us get started...');\\n// pass in a message with an action that will cause gotoThread to be called...\\nconversation.addAction('continuation');\\n\\nconversation.addMessage('This is a different thread completely', 'continuation');\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 404,\n                      \"name\": \"message\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"Message template to be sent\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"reference\",\n                            \"typeArguments\": [\n                              {\n                                \"type\": \"reference\",\n                                \"id\": 329,\n                                \"name\": \"BotkitMessageTemplate\"\n                              }\n                            ],\n                            \"name\": \"Partial\"\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        ]\n                      }\n                    },\n                    {\n                      \"id\": 405,\n                      \"name\": \"thread_name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"Name of thread to which message will be added\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 379,\n                    \"name\": \"BotkitConversation\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 282,\n                  \"character\": 21\n                }\n              ]\n            },\n            {\n              \"id\": 413,\n              \"name\": \"addQuestion\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 414,\n                  \"name\": \"addQuestion\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Identical to [ask()](#ask), but accepts the name of a thread to which the question is added.\",\n                    \"text\": \"[Learn more about building conversations &rarr;](../conversations.md#build-a-conversation)\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 415,\n                      \"name\": \"message\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A message that will be used as the prompt\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"reference\",\n                            \"typeArguments\": [\n                              {\n                                \"type\": \"reference\",\n                                \"id\": 329,\n                                \"name\": \"BotkitMessageTemplate\"\n                              }\n                            ],\n                            \"name\": \"Partial\"\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        ]\n                      }\n                    },\n                    {\n                      \"id\": 416,\n                      \"name\": \"handlers\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"One or more handler functions defining possible conditional actions based on the response to the question\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"reference\",\n                            \"id\": 318,\n                            \"name\": \"BotkitConvoHandler\"\n                          },\n                          {\n                            \"type\": \"array\",\n                            \"elementType\": {\n                              \"type\": \"reference\",\n                              \"id\": 324,\n                              \"name\": \"BotkitConvoTrigger\"\n                            }\n                          }\n                        ]\n                      }\n                    },\n                    {\n                      \"id\": 417,\n                      \"name\": \"key\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"Name of variable to store response in.\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"reflection\",\n                            \"declaration\": {\n                              \"id\": 418,\n                              \"name\": \"__type\",\n                              \"kind\": 65536,\n                              \"kindString\": \"Type literal\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"children\": [\n                                {\n                                  \"id\": 419,\n                                  \"name\": \"key\",\n                                  \"kind\": 32,\n                                  \"kindString\": \"Variable\",\n                                  \"flags\": {\n                                    \"isExported\": true,\n                                    \"isExternal\": true\n                                  },\n                                  \"sources\": [\n                                    {\n                                      \"fileName\": \"conversation.ts\",\n                                      \"line\": 358,\n                                      \"character\": 135\n                                    }\n                                  ],\n                                  \"type\": {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"string\"\n                                  }\n                                }\n                              ],\n                              \"groups\": [\n                                {\n                                  \"title\": \"Variables\",\n                                  \"kind\": 32,\n                                  \"children\": [\n                                    419\n                                  ]\n                                }\n                              ],\n                              \"sources\": [\n                                {\n                                  \"fileName\": \"conversation.ts\",\n                                  \"line\": 358,\n                                  \"character\": 130\n                                }\n                              ]\n                            }\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"null\"\n                          }\n                        ]\n                      }\n                    },\n                    {\n                      \"id\": 420,\n                      \"name\": \"thread_name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"Name of thread to which message will be added\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 379,\n                    \"name\": \"BotkitConversation\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 358,\n                  \"character\": 22\n                }\n              ]\n            },\n            {\n              \"id\": 429,\n              \"name\": \"after\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 430,\n                  \"name\": \"after\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Bind a function to run after the dialog has completed.\\nThe first parameter to the handler will include a hash of all variables set and values collected from the user during the conversation.\\nThe second parameter to the handler is a BotWorker object that can be used to start new dialogs or take other actions.\",\n                    \"text\": \"[Learn more about handling end of conversation](../conversations.md#handling-end-of-conversation)\\n```javascript\\nlet convo = new BotkitConversation(MY_CONVO, controller);\\nconvo.ask('What is your name?', [], 'name');\\nconvo.ask('What is your age?', [], 'age');\\nconvo.ask('What is your favorite color?', [], 'color');\\nconvo.after(async(results, bot) => {\\n\\n     // handle results.name, results.age, results.color\\n\\n});\\ncontroller.addDialog(convo);\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 431,\n                      \"name\": \"handler\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"in the form async(results, bot) { ... }\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 432,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 433,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 434,\n                                  \"name\": \"results\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"any\"\n                                  }\n                                },\n                                {\n                                  \"id\": 435,\n                                  \"name\": \"bot\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"id\": 2,\n                                    \"name\": \"BotWorker\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"intrinsic\",\n                                \"name\": \"void\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"conversation.ts\",\n                              \"line\": 471,\n                              \"character\": 25\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 471,\n                  \"character\": 16\n                }\n              ]\n            },\n            {\n              \"id\": 406,\n              \"name\": \"ask\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 407,\n                  \"name\": \"ask\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Add a question to the default thread.\\nIn addition to a message template, receives either a single handler function to call when an answer is provided,\\nor an array of handlers paired with trigger patterns. When providing multiple conditions to test, developers may also provide a\\nhandler marked as the default choice.\",\n                    \"text\": \"[Learn more about building conversations &rarr;](../conversations.md#build-a-conversation)\\n```javascript\\n// ask a question, handle the response with a function\\nconvo.ask('What is your name?', async(response, convo, bot, full_message) => {\\n await bot.say('Oh your name is ' + response);\\n}, {key: 'name'});\\n\\n// ask a question, evaluate answer, take conditional action based on response\\nconvo.ask('Do you want to eat a taco?', [\\n {\\n     pattern: 'yes',\\n     type: 'string',\\n     handler: async(response_text, convo, bot, full_message) => {\\n         return await convo.gotoThread('yes_taco');\\n     }\\n },\\n {\\n     pattern: 'no',\\n     type: 'string',\\n     handler: async(response_text, convo, bot, full_message) => {\\n         return await convo.gotoThread('no_taco');\\n     }\\n  },\\n  {\\n      default: true,\\n      handler: async(response_text, convo, bot, full_message) => {\\n          await bot.say('I do not understand your response!');\\n          // start over!\\n          return await convo.repeat();\\n      }\\n  }\\n], {key: 'tacos'});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 408,\n                      \"name\": \"message\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"a message that will be used as the prompt\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"reference\",\n                            \"typeArguments\": [\n                              {\n                                \"type\": \"reference\",\n                                \"id\": 329,\n                                \"name\": \"BotkitMessageTemplate\"\n                              }\n                            ],\n                            \"name\": \"Partial\"\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        ]\n                      }\n                    },\n                    {\n                      \"id\": 409,\n                      \"name\": \"handlers\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"one or more handler functions defining possible conditional actions based on the response to the question.\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"reference\",\n                            \"id\": 318,\n                            \"name\": \"BotkitConvoHandler\"\n                          },\n                          {\n                            \"type\": \"array\",\n                            \"elementType\": {\n                              \"type\": \"reference\",\n                              \"id\": 324,\n                              \"name\": \"BotkitConvoTrigger\"\n                            }\n                          }\n                        ]\n                      }\n                    },\n                    {\n                      \"id\": 410,\n                      \"name\": \"key\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"name of variable to store response in.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"reflection\",\n                            \"declaration\": {\n                              \"id\": 411,\n                              \"name\": \"__type\",\n                              \"kind\": 65536,\n                              \"kindString\": \"Type literal\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"children\": [\n                                {\n                                  \"id\": 412,\n                                  \"name\": \"key\",\n                                  \"kind\": 32,\n                                  \"kindString\": \"Variable\",\n                                  \"flags\": {\n                                    \"isExported\": true,\n                                    \"isExternal\": true\n                                  },\n                                  \"sources\": [\n                                    {\n                                      \"fileName\": \"conversation.ts\",\n                                      \"line\": 344,\n                                      \"character\": 127\n                                    }\n                                  ],\n                                  \"type\": {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"string\"\n                                  }\n                                }\n                              ],\n                              \"groups\": [\n                                {\n                                  \"title\": \"Variables\",\n                                  \"kind\": 32,\n                                  \"children\": [\n                                    412\n                                  ]\n                                }\n                              ],\n                              \"sources\": [\n                                {\n                                  \"fileName\": \"conversation.ts\",\n                                  \"line\": 344,\n                                  \"character\": 122\n                                }\n                              ]\n                            }\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"null\"\n                          }\n                        ]\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 379,\n                    \"name\": \"BotkitConversation\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 344,\n                  \"character\": 14\n                }\n              ]\n            },\n            {\n              \"id\": 421,\n              \"name\": \"before\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 422,\n                  \"name\": \"before\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Register a handler function that will fire before a given thread begins.\\nUse this hook to set variables, call APIs, or change the flow of the conversation using `convo.gotoThread`\",\n                    \"text\": \"```javascript\\nconvo.addMessage('This is the foo thread: var == {{vars.foo}}', 'foo');\\nconvo.before('foo', async(convo, bot) => {\\n // set a variable here that can be used in the message template\\n convo.setVar('foo','THIS IS FOO');\\n\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 423,\n                      \"name\": \"thread_name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A valid thread defined in this conversation\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 424,\n                      \"name\": \"handler\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A handler function in the form async(convo, bot) => { ... }\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 425,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 426,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 427,\n                                  \"name\": \"convo\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"id\": 297,\n                                    \"name\": \"BotkitDialogWrapper\"\n                                  }\n                                },\n                                {\n                                  \"id\": 428,\n                                  \"name\": \"bot\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"id\": 2,\n                                    \"name\": \"BotWorker\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"any\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"conversation.ts\",\n                              \"line\": 419,\n                              \"character\": 47\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 419,\n                  \"character\": 17\n                }\n              ]\n            },\n            {\n              \"id\": 436,\n              \"name\": \"onChange\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 437,\n                  \"name\": \"onChange\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Bind a function to run whenever a user answers a specific question.  Can be used to validate input and take conditional actions.\",\n                    \"text\": \"```javascript\\nconvo.ask('What is your name?', [], 'name');\\nconvo.onChange('name', async(response, convo, bot) => {\\n\\n // user changed their name!\\n // do something...\\n\\n});\\n```\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 438,\n                      \"name\": \"variable\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"name of the variable to watch for changes\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 439,\n                      \"name\": \"handler\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"a handler function that will fire whenever a user's response is used to change the value of the watched variable\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 440,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 441,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 442,\n                                  \"name\": \"response\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"any\"\n                                  }\n                                },\n                                {\n                                  \"id\": 443,\n                                  \"name\": \"convo\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"any\"\n                                  }\n                                },\n                                {\n                                  \"id\": 444,\n                                  \"name\": \"bot\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"any\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"any\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"conversation.ts\",\n                              \"line\": 506,\n                              \"character\": 46\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 506,\n                  \"character\": 19\n                }\n              ]\n            },\n            {\n              \"id\": 386,\n              \"name\": \"say\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 387,\n                  \"name\": \"say\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Add a non-interactive message to the default thread.\\nMessages added with `say()` and `addMessage()` will _not_ wait for a response, will be sent one after another without a pause.\",\n                    \"text\": \"[Learn more about building conversations &rarr;](../conversations.md#build-a-conversation)\\n\\n```javascript\\nlet conversation = new BotkitConversation('welcome', controller);\\nconversation.say('Hello! Welcome to my app.');\\nconversation.say('Let us get started...');\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 388,\n                      \"name\": \"message\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"Message template to be sent\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"reference\",\n                            \"typeArguments\": [\n                              {\n                                \"type\": \"reference\",\n                                \"id\": 329,\n                                \"name\": \"BotkitMessageTemplate\"\n                              }\n                            ],\n                            \"name\": \"Partial\"\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        ]\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 379,\n                    \"name\": \"BotkitConversation\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 167,\n                  \"character\": 14\n                }\n              ]\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Constructors\",\n              \"kind\": 512,\n              \"children\": [\n                382\n              ]\n            },\n            {\n              \"title\": \"Properties\",\n              \"kind\": 1024,\n              \"children\": [\n                381\n              ]\n            },\n            {\n              \"title\": \"Methods\",\n              \"kind\": 2048,\n              \"children\": [\n                389,\n                393,\n                398,\n                402,\n                413,\n                429,\n                406,\n                421,\n                436,\n                386\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"conversation.ts\",\n              \"line\": 115,\n              \"character\": 31\n            }\n          ],\n          \"extendedTypes\": [\n            {\n              \"type\": \"intrinsic\",\n              \"name\": \"any\"\n            }\n          ],\n          \"props\": [\n            {\n              \"id\": 381,\n              \"name\": \"script\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A map of every message in the dialog, broken into threads\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 119,\n                  \"character\": 17\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"any\"\n              }\n            }\n          ],\n          \"methods\": [\n            {\n              \"id\": 389,\n              \"name\": \"addAction\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 390,\n                  \"name\": \"addAction\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"An an action to the conversation timeline. This can be used to go to switch threads or end the dialog.\",\n                    \"text\": \"When provided the name of another thread in the conversation, this will cause the bot to go immediately\\nto that thread.\\n\\nOtherwise, use one of the following keywords:\\n* `stop`\\n* `repeat`\\n* `complete`\\n* `timeout`\\n\\n[Learn more about building conversations &rarr;](../conversations.md#build-a-conversation)\\n\\n```javascript\\n\\n// go to a thread called \\\"next_thread\\\"\\nconvo.addAction('next_thread');\\n\\n// end the conversation and mark as successful\\nconvo.addAction('complete');\\n```\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 391,\n                      \"name\": \"action\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An action or thread name\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 392,\n                      \"name\": \"thread_name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"The name of the thread to which this action is added.  Defaults to `default`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      },\n                      \"defaultValue\": \"\\\"default\\\"\"\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 379,\n                    \"name\": \"BotkitConversation\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 197,\n                  \"character\": 20\n                }\n              ]\n            },\n            {\n              \"id\": 393,\n              \"name\": \"addChildDialog\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 394,\n                  \"name\": \"addChildDialog\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Cause the dialog to call a child dialog, wait for it to complete,\\nthen store the results in a variable and resume the parent dialog.\\nUse this to [combine multiple dialogs into bigger interactions.](../conversations.md#composing-dialogs)\",\n                    \"text\": \"[Learn more about building conversations &rarr;](../conversations.md#build-a-conversation)\\n```javascript\\n// define a profile collection dialog\\nlet profileDialog = new BotkitConversation('PROFILE_DIALOG', controller);\\nprofileDialog.ask('What is your name?', async(res, convo, bot) => {}, {key: 'name'});\\nprofileDialog.ask('What is your age?', async(res, convo, bot) => {}, {key: 'age'});\\nprofileDialog.ask('What is your location?', async(res, convo, bot) => {}, {key: 'location'});\\ncontroller.addDialog(profileDialog);\\n\\nlet onboard = new BotkitConversation('ONBOARDING', controller);\\nonboard.say('Hello! It is time to collect your profile data.');\\nonboard.addChildDialog('PROFILE_DIALOG', 'profile');\\nonboard.say('Hello, {{vars.profile.name}}! Onboarding is complete.');\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 395,\n                      \"name\": \"dialog_id\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"the id of another dialog\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 396,\n                      \"name\": \"key_name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"the variable name in which to store the results of the child dialog. if not provided, defaults to dialog_id.\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 397,\n                      \"name\": \"thread_name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"the name of a thread to which this call should be added. defaults to 'default'\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      },\n                      \"defaultValue\": \"\\\"default\\\"\"\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 379,\n                    \"name\": \"BotkitConversation\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 226,\n                  \"character\": 25\n                }\n              ]\n            },\n            {\n              \"id\": 398,\n              \"name\": \"addGotoDialog\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 399,\n                  \"name\": \"addGotoDialog\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Cause the current dialog to handoff to another dialog.\\nThe parent dialog will not resume when the child dialog completes. However, the afterDialog event will not fire for the parent dialog until all child dialogs complete.\\nUse this to [combine multiple dialogs into bigger interactions.](../conversations.md#composing-dialogs)\",\n                    \"text\": \"[Learn more about building conversations &rarr;](../conversations.md#build-a-conversation)\\n```javascript\\nlet parent = new BotkitConversation('parent', controller);\\nlet child = new BotkitConversation('child', controller);\\nparent.say('Moving on....');\\nparent.addGotoDialog('child');\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 400,\n                      \"name\": \"dialog_id\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"the id of another dialog\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 401,\n                      \"name\": \"thread_name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"the name of a thread to which this call should be added. defaults to 'default'\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      },\n                      \"defaultValue\": \"\\\"default\\\"\"\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 379,\n                    \"name\": \"BotkitConversation\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 253,\n                  \"character\": 24\n                }\n              ]\n            },\n            {\n              \"id\": 402,\n              \"name\": \"addMessage\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 403,\n                  \"name\": \"addMessage\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Add a message template to a specific thread.\\nMessages added with `say()` and `addMessage()` will be sent one after another without a pause.\",\n                    \"text\": \"[Learn more about building conversations &rarr;](../conversations.md#build-a-conversation)\\n```javascript\\nlet conversation = new BotkitConversation('welcome', controller);\\nconversation.say('Hello! Welcome to my app.');\\nconversation.say('Let us get started...');\\n// pass in a message with an action that will cause gotoThread to be called...\\nconversation.addAction('continuation');\\n\\nconversation.addMessage('This is a different thread completely', 'continuation');\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 404,\n                      \"name\": \"message\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"Message template to be sent\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"reference\",\n                            \"typeArguments\": [\n                              {\n                                \"type\": \"reference\",\n                                \"id\": 329,\n                                \"name\": \"BotkitMessageTemplate\"\n                              }\n                            ],\n                            \"name\": \"Partial\"\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        ]\n                      }\n                    },\n                    {\n                      \"id\": 405,\n                      \"name\": \"thread_name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"Name of thread to which message will be added\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 379,\n                    \"name\": \"BotkitConversation\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 282,\n                  \"character\": 21\n                }\n              ]\n            },\n            {\n              \"id\": 413,\n              \"name\": \"addQuestion\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 414,\n                  \"name\": \"addQuestion\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Identical to [ask()](#ask), but accepts the name of a thread to which the question is added.\",\n                    \"text\": \"[Learn more about building conversations &rarr;](../conversations.md#build-a-conversation)\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 415,\n                      \"name\": \"message\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A message that will be used as the prompt\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"reference\",\n                            \"typeArguments\": [\n                              {\n                                \"type\": \"reference\",\n                                \"id\": 329,\n                                \"name\": \"BotkitMessageTemplate\"\n                              }\n                            ],\n                            \"name\": \"Partial\"\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        ]\n                      }\n                    },\n                    {\n                      \"id\": 416,\n                      \"name\": \"handlers\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"One or more handler functions defining possible conditional actions based on the response to the question\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"reference\",\n                            \"id\": 318,\n                            \"name\": \"BotkitConvoHandler\"\n                          },\n                          {\n                            \"type\": \"array\",\n                            \"elementType\": {\n                              \"type\": \"reference\",\n                              \"id\": 324,\n                              \"name\": \"BotkitConvoTrigger\"\n                            }\n                          }\n                        ]\n                      }\n                    },\n                    {\n                      \"id\": 417,\n                      \"name\": \"key\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"Name of variable to store response in.\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"reflection\",\n                            \"declaration\": {\n                              \"id\": 418,\n                              \"name\": \"__type\",\n                              \"kind\": 65536,\n                              \"kindString\": \"Type literal\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"children\": [\n                                {\n                                  \"id\": 419,\n                                  \"name\": \"key\",\n                                  \"kind\": 32,\n                                  \"kindString\": \"Variable\",\n                                  \"flags\": {\n                                    \"isExported\": true,\n                                    \"isExternal\": true\n                                  },\n                                  \"sources\": [\n                                    {\n                                      \"fileName\": \"conversation.ts\",\n                                      \"line\": 358,\n                                      \"character\": 135\n                                    }\n                                  ],\n                                  \"type\": {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"string\"\n                                  }\n                                }\n                              ],\n                              \"groups\": [\n                                {\n                                  \"title\": \"Variables\",\n                                  \"kind\": 32,\n                                  \"children\": [\n                                    419\n                                  ]\n                                }\n                              ],\n                              \"sources\": [\n                                {\n                                  \"fileName\": \"conversation.ts\",\n                                  \"line\": 358,\n                                  \"character\": 130\n                                }\n                              ]\n                            }\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"null\"\n                          }\n                        ]\n                      }\n                    },\n                    {\n                      \"id\": 420,\n                      \"name\": \"thread_name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"Name of thread to which message will be added\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 379,\n                    \"name\": \"BotkitConversation\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 358,\n                  \"character\": 22\n                }\n              ]\n            },\n            {\n              \"id\": 429,\n              \"name\": \"after\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 430,\n                  \"name\": \"after\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Bind a function to run after the dialog has completed.\\nThe first parameter to the handler will include a hash of all variables set and values collected from the user during the conversation.\\nThe second parameter to the handler is a BotWorker object that can be used to start new dialogs or take other actions.\",\n                    \"text\": \"[Learn more about handling end of conversation](../conversations.md#handling-end-of-conversation)\\n```javascript\\nlet convo = new BotkitConversation(MY_CONVO, controller);\\nconvo.ask('What is your name?', [], 'name');\\nconvo.ask('What is your age?', [], 'age');\\nconvo.ask('What is your favorite color?', [], 'color');\\nconvo.after(async(results, bot) => {\\n\\n     // handle results.name, results.age, results.color\\n\\n});\\ncontroller.addDialog(convo);\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 431,\n                      \"name\": \"handler\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"in the form async(results, bot) { ... }\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 432,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 433,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 434,\n                                  \"name\": \"results\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"any\"\n                                  }\n                                },\n                                {\n                                  \"id\": 435,\n                                  \"name\": \"bot\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"id\": 2,\n                                    \"name\": \"BotWorker\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"intrinsic\",\n                                \"name\": \"void\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"conversation.ts\",\n                              \"line\": 471,\n                              \"character\": 25\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 471,\n                  \"character\": 16\n                }\n              ]\n            },\n            {\n              \"id\": 406,\n              \"name\": \"ask\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 407,\n                  \"name\": \"ask\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Add a question to the default thread.\\nIn addition to a message template, receives either a single handler function to call when an answer is provided,\\nor an array of handlers paired with trigger patterns. When providing multiple conditions to test, developers may also provide a\\nhandler marked as the default choice.\",\n                    \"text\": \"[Learn more about building conversations &rarr;](../conversations.md#build-a-conversation)\\n```javascript\\n// ask a question, handle the response with a function\\nconvo.ask('What is your name?', async(response, convo, bot, full_message) => {\\n await bot.say('Oh your name is ' + response);\\n}, {key: 'name'});\\n\\n// ask a question, evaluate answer, take conditional action based on response\\nconvo.ask('Do you want to eat a taco?', [\\n {\\n     pattern: 'yes',\\n     type: 'string',\\n     handler: async(response_text, convo, bot, full_message) => {\\n         return await convo.gotoThread('yes_taco');\\n     }\\n },\\n {\\n     pattern: 'no',\\n     type: 'string',\\n     handler: async(response_text, convo, bot, full_message) => {\\n         return await convo.gotoThread('no_taco');\\n     }\\n  },\\n  {\\n      default: true,\\n      handler: async(response_text, convo, bot, full_message) => {\\n          await bot.say('I do not understand your response!');\\n          // start over!\\n          return await convo.repeat();\\n      }\\n  }\\n], {key: 'tacos'});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 408,\n                      \"name\": \"message\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"a message that will be used as the prompt\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"reference\",\n                            \"typeArguments\": [\n                              {\n                                \"type\": \"reference\",\n                                \"id\": 329,\n                                \"name\": \"BotkitMessageTemplate\"\n                              }\n                            ],\n                            \"name\": \"Partial\"\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        ]\n                      }\n                    },\n                    {\n                      \"id\": 409,\n                      \"name\": \"handlers\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"one or more handler functions defining possible conditional actions based on the response to the question.\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"reference\",\n                            \"id\": 318,\n                            \"name\": \"BotkitConvoHandler\"\n                          },\n                          {\n                            \"type\": \"array\",\n                            \"elementType\": {\n                              \"type\": \"reference\",\n                              \"id\": 324,\n                              \"name\": \"BotkitConvoTrigger\"\n                            }\n                          }\n                        ]\n                      }\n                    },\n                    {\n                      \"id\": 410,\n                      \"name\": \"key\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"name of variable to store response in.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"reflection\",\n                            \"declaration\": {\n                              \"id\": 411,\n                              \"name\": \"__type\",\n                              \"kind\": 65536,\n                              \"kindString\": \"Type literal\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"children\": [\n                                {\n                                  \"id\": 412,\n                                  \"name\": \"key\",\n                                  \"kind\": 32,\n                                  \"kindString\": \"Variable\",\n                                  \"flags\": {\n                                    \"isExported\": true,\n                                    \"isExternal\": true\n                                  },\n                                  \"sources\": [\n                                    {\n                                      \"fileName\": \"conversation.ts\",\n                                      \"line\": 344,\n                                      \"character\": 127\n                                    }\n                                  ],\n                                  \"type\": {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"string\"\n                                  }\n                                }\n                              ],\n                              \"groups\": [\n                                {\n                                  \"title\": \"Variables\",\n                                  \"kind\": 32,\n                                  \"children\": [\n                                    412\n                                  ]\n                                }\n                              ],\n                              \"sources\": [\n                                {\n                                  \"fileName\": \"conversation.ts\",\n                                  \"line\": 344,\n                                  \"character\": 122\n                                }\n                              ]\n                            }\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"null\"\n                          }\n                        ]\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 379,\n                    \"name\": \"BotkitConversation\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 344,\n                  \"character\": 14\n                }\n              ]\n            },\n            {\n              \"id\": 421,\n              \"name\": \"before\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 422,\n                  \"name\": \"before\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Register a handler function that will fire before a given thread begins.\\nUse this hook to set variables, call APIs, or change the flow of the conversation using `convo.gotoThread`\",\n                    \"text\": \"```javascript\\nconvo.addMessage('This is the foo thread: var == {{vars.foo}}', 'foo');\\nconvo.before('foo', async(convo, bot) => {\\n // set a variable here that can be used in the message template\\n convo.setVar('foo','THIS IS FOO');\\n\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 423,\n                      \"name\": \"thread_name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A valid thread defined in this conversation\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 424,\n                      \"name\": \"handler\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A handler function in the form async(convo, bot) => { ... }\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 425,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 426,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 427,\n                                  \"name\": \"convo\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"id\": 297,\n                                    \"name\": \"BotkitDialogWrapper\"\n                                  }\n                                },\n                                {\n                                  \"id\": 428,\n                                  \"name\": \"bot\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"id\": 2,\n                                    \"name\": \"BotWorker\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"any\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"conversation.ts\",\n                              \"line\": 419,\n                              \"character\": 47\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 419,\n                  \"character\": 17\n                }\n              ]\n            },\n            {\n              \"id\": 436,\n              \"name\": \"onChange\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 437,\n                  \"name\": \"onChange\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Bind a function to run whenever a user answers a specific question.  Can be used to validate input and take conditional actions.\",\n                    \"text\": \"```javascript\\nconvo.ask('What is your name?', [], 'name');\\nconvo.onChange('name', async(response, convo, bot) => {\\n\\n // user changed their name!\\n // do something...\\n\\n});\\n```\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 438,\n                      \"name\": \"variable\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"name of the variable to watch for changes\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 439,\n                      \"name\": \"handler\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"a handler function that will fire whenever a user's response is used to change the value of the watched variable\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 440,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 441,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 442,\n                                  \"name\": \"response\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"any\"\n                                  }\n                                },\n                                {\n                                  \"id\": 443,\n                                  \"name\": \"convo\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"any\"\n                                  }\n                                },\n                                {\n                                  \"id\": 444,\n                                  \"name\": \"bot\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"any\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"any\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"conversation.ts\",\n                              \"line\": 506,\n                              \"character\": 46\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 506,\n                  \"character\": 19\n                }\n              ]\n            },\n            {\n              \"id\": 386,\n              \"name\": \"say\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 387,\n                  \"name\": \"say\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Add a non-interactive message to the default thread.\\nMessages added with `say()` and `addMessage()` will _not_ wait for a response, will be sent one after another without a pause.\",\n                    \"text\": \"[Learn more about building conversations &rarr;](../conversations.md#build-a-conversation)\\n\\n```javascript\\nlet conversation = new BotkitConversation('welcome', controller);\\nconversation.say('Hello! Welcome to my app.');\\nconversation.say('Let us get started...');\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 388,\n                      \"name\": \"message\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"Message template to be sent\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"reference\",\n                            \"typeArguments\": [\n                              {\n                                \"type\": \"reference\",\n                                \"id\": 329,\n                                \"name\": \"BotkitMessageTemplate\"\n                              }\n                            ],\n                            \"name\": \"Partial\"\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        ]\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 379,\n                    \"name\": \"BotkitConversation\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 167,\n                  \"character\": 14\n                }\n              ]\n            }\n          ],\n          \"constructors\": [\n            {\n              \"id\": 382,\n              \"name\": \"constructor\",\n              \"kind\": 512,\n              \"kindString\": \"Constructor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Create a new BotkitConversation object\"\n              },\n              \"signatures\": [\n                {\n                  \"id\": 383,\n                  \"name\": \"new BotkitConversation\",\n                  \"kind\": 16384,\n                  \"kindString\": \"Constructor signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Create a new BotkitConversation object\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 384,\n                      \"name\": \"dialogId\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"A unique identifier for this dialog, used to later trigger this dialog\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 385,\n                      \"name\": \"controller\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"A pointer to the main Botkit controller\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 185,\n                        \"name\": \"Botkit\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 379,\n                    \"name\": \"BotkitConversation\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 125,\n                  \"character\": 32\n                }\n              ]\n            }\n          ]\n        },\n        {\n          \"id\": 297,\n          \"name\": \"BotkitDialogWrapper\",\n          \"kind\": 128,\n          \"kindString\": \"Class\",\n          \"flags\": {\n            \"isExported\": true,\n            \"isExternal\": true\n          },\n          \"comment\": {\n            \"shortText\": \"This class is used to provide easy access to common actions taken on active BotkitConversation instances.\\nThese objects are passed into handlers bound to BotkitConversations using .before .onChange and conditional handler functions passed to .ask and .addQuestion\\nGrants access to convo.vars convo.gotoThread() convo.setVar() and convo.repeat().\"\n          },\n          \"children\": [\n            {\n              \"id\": 302,\n              \"name\": \"constructor\",\n              \"kind\": 512,\n              \"kindString\": \"Constructor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 303,\n                  \"name\": \"new BotkitDialogWrapper\",\n                  \"kind\": 16384,\n                  \"kindString\": \"Constructor signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 304,\n                      \"name\": \"dc\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"DialogContext\"\n                      }\n                    },\n                    {\n                      \"id\": 305,\n                      \"name\": \"step\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 366,\n                        \"name\": \"BotkitConversationStep\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 297,\n                    \"name\": \"BotkitDialogWrapper\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"dialogWrapper.ts\",\n                  \"line\": 25,\n                  \"character\": 5\n                }\n              ]\n            },\n            {\n              \"id\": 298,\n              \"name\": \"vars\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"An object containing variables and user responses from this conversation.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"dialogWrapper.ts\",\n                  \"line\": 23,\n                  \"character\": 15\n                }\n              ],\n              \"type\": {\n                \"type\": \"reflection\",\n                \"declaration\": {\n                  \"id\": 299,\n                  \"name\": \"__type\",\n                  \"kind\": 65536,\n                  \"kindString\": \"Type literal\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"indexSignature\": [\n                    {\n                      \"id\": 300,\n                      \"name\": \"__index\",\n                      \"kind\": 8192,\n                      \"kindString\": \"Index signature\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"parameters\": [\n                        {\n                          \"id\": 301,\n                          \"name\": \"key\",\n                          \"kind\": 32768,\n                          \"kindString\": \"Parameter\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"type\": {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        }\n                      ],\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"sources\": [\n                    {\n                      \"fileName\": \"dialogWrapper.ts\",\n                      \"line\": 23,\n                      \"character\": 16\n                    }\n                  ]\n                }\n              }\n            },\n            {\n              \"id\": 306,\n              \"name\": \"gotoThread\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 307,\n                  \"name\": \"gotoThread\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Jump immediately to the first message in a different thread.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 308,\n                      \"name\": \"thread\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"Name of a thread\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"dialogWrapper.ts\",\n                  \"line\": 37,\n                  \"character\": 27\n                }\n              ]\n            },\n            {\n              \"id\": 309,\n              \"name\": \"repeat\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 310,\n                  \"name\": \"repeat\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Repeat the last message sent on the next turn.\"\n                  },\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"dialogWrapper.ts\",\n                  \"line\": 45,\n                  \"character\": 23\n                }\n              ]\n            },\n            {\n              \"id\": 313,\n              \"name\": \"setVar\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 314,\n                  \"name\": \"setVar\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Set the value of a variable that will be available to messages in the conversation.\\nEquivalent to convo.vars.key = val;\\nResults in {{vars.key}} being replaced with the value in val.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 315,\n                      \"name\": \"key\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"the name of the variable\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 316,\n                      \"name\": \"val\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"the value for the variable\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"dialogWrapper.ts\",\n                  \"line\": 65,\n                  \"character\": 17\n                }\n              ]\n            },\n            {\n              \"id\": 311,\n              \"name\": \"stop\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 312,\n                  \"name\": \"stop\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Stop the dialog.\"\n                  },\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"dialogWrapper.ts\",\n                  \"line\": 53,\n                  \"character\": 21\n                }\n              ]\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Constructors\",\n              \"kind\": 512,\n              \"children\": [\n                302\n              ]\n            },\n            {\n              \"title\": \"Properties\",\n              \"kind\": 1024,\n              \"children\": [\n                298\n              ]\n            },\n            {\n              \"title\": \"Methods\",\n              \"kind\": 2048,\n              \"children\": [\n                306,\n                309,\n                313,\n                311\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"dialogWrapper.ts\",\n              \"line\": 17,\n              \"character\": 32\n            }\n          ],\n          \"props\": [\n            {\n              \"id\": 298,\n              \"name\": \"vars\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"An object containing variables and user responses from this conversation.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"dialogWrapper.ts\",\n                  \"line\": 23,\n                  \"character\": 15\n                }\n              ],\n              \"type\": {\n                \"type\": \"reflection\",\n                \"declaration\": {\n                  \"id\": 299,\n                  \"name\": \"__type\",\n                  \"kind\": 65536,\n                  \"kindString\": \"Type literal\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"indexSignature\": [\n                    {\n                      \"id\": 300,\n                      \"name\": \"__index\",\n                      \"kind\": 8192,\n                      \"kindString\": \"Index signature\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"parameters\": [\n                        {\n                          \"id\": 301,\n                          \"name\": \"key\",\n                          \"kind\": 32768,\n                          \"kindString\": \"Parameter\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"type\": {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        }\n                      ],\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"sources\": [\n                    {\n                      \"fileName\": \"dialogWrapper.ts\",\n                      \"line\": 23,\n                      \"character\": 16\n                    }\n                  ]\n                }\n              }\n            }\n          ],\n          \"methods\": [\n            {\n              \"id\": 306,\n              \"name\": \"gotoThread\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 307,\n                  \"name\": \"gotoThread\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Jump immediately to the first message in a different thread.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 308,\n                      \"name\": \"thread\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"Name of a thread\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"dialogWrapper.ts\",\n                  \"line\": 37,\n                  \"character\": 27\n                }\n              ]\n            },\n            {\n              \"id\": 309,\n              \"name\": \"repeat\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 310,\n                  \"name\": \"repeat\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Repeat the last message sent on the next turn.\"\n                  },\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"dialogWrapper.ts\",\n                  \"line\": 45,\n                  \"character\": 23\n                }\n              ]\n            },\n            {\n              \"id\": 313,\n              \"name\": \"setVar\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 314,\n                  \"name\": \"setVar\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Set the value of a variable that will be available to messages in the conversation.\\nEquivalent to convo.vars.key = val;\\nResults in {{vars.key}} being replaced with the value in val.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 315,\n                      \"name\": \"key\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"the name of the variable\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 316,\n                      \"name\": \"val\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"the value for the variable\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"dialogWrapper.ts\",\n                  \"line\": 65,\n                  \"character\": 17\n                }\n              ]\n            },\n            {\n              \"id\": 311,\n              \"name\": \"stop\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 312,\n                  \"name\": \"stop\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Stop the dialog.\"\n                  },\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"dialogWrapper.ts\",\n                  \"line\": 53,\n                  \"character\": 21\n                }\n              ]\n            }\n          ],\n          \"constructors\": [\n            {\n              \"id\": 302,\n              \"name\": \"constructor\",\n              \"kind\": 512,\n              \"kindString\": \"Constructor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 303,\n                  \"name\": \"new BotkitDialogWrapper\",\n                  \"kind\": 16384,\n                  \"kindString\": \"Constructor signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 304,\n                      \"name\": \"dc\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"DialogContext\"\n                      }\n                    },\n                    {\n                      \"id\": 305,\n                      \"name\": \"step\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 366,\n                        \"name\": \"BotkitConversationStep\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 297,\n                    \"name\": \"BotkitDialogWrapper\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"dialogWrapper.ts\",\n                  \"line\": 25,\n                  \"character\": 5\n                }\n              ]\n            }\n          ]\n        },\n        {\n          \"id\": 462,\n          \"name\": \"BotkitTestClient\",\n          \"kind\": 128,\n          \"kindString\": \"Class\",\n          \"flags\": {\n            \"isExported\": true,\n            \"isExternal\": true\n          },\n          \"comment\": {\n            \"shortText\": \"A client for testing dialogs in isolation.\"\n          },\n          \"children\": [\n            {\n              \"id\": 465,\n              \"name\": \"constructor\",\n              \"kind\": 512,\n              \"kindString\": \"Constructor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Create a BotkitTestClient to test a dialog without having to create a full-fledged adapter.\",\n                \"text\": \"```javascript\\nlet client = new BotkitTestClient('test', bot, MY_DIALOG, MY_OPTIONS);\\nlet reply = await client.sendActivity('first message');\\nassert.strictEqual(reply.text, 'first reply', 'reply failed');\\n```\\n\"\n              },\n              \"signatures\": [\n                {\n                  \"id\": 466,\n                  \"name\": \"new BotkitTestClient\",\n                  \"kind\": 16384,\n                  \"kindString\": \"Constructor signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Create a BotkitTestClient to test a dialog without having to create a full-fledged adapter.\",\n                    \"text\": \"```javascript\\nlet client = new BotkitTestClient('test', bot, MY_DIALOG, MY_OPTIONS);\\nlet reply = await client.sendActivity('first message');\\nassert.strictEqual(reply.text, 'first reply', 'reply failed');\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 467,\n                      \"name\": \"channelId\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"The channelId to be used for the test.\\nUse 'emulator' or 'test' if you are uncertain of the channel you are targeting.\\nOtherwise, it is recommended that you use the id for the channel(s) your bot will be using and write a test case for each channel.\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 468,\n                      \"name\": \"bot\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"(Required) The Botkit bot that has the skill to test.\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 185,\n                        \"name\": \"Botkit\"\n                      }\n                    },\n                    {\n                      \"id\": 469,\n                      \"name\": \"dialogToTest\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"(Required) The identifier of the skill to test in the bot.\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          },\n                          {\n                            \"type\": \"array\",\n                            \"elementType\": {\n                              \"type\": \"intrinsic\",\n                              \"name\": \"string\"\n                            }\n                          }\n                        ]\n                      }\n                    },\n                    {\n                      \"id\": 470,\n                      \"name\": \"initialDialogOptions\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"(Optional) additional argument(s) to pass to the dialog being started.\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 471,\n                      \"name\": \"middlewares\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"(Optional) a stack of middleware to be run when testing\"\n                      },\n                      \"type\": {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"reference\",\n                          \"name\": \"Middleware\"\n                        }\n                      }\n                    },\n                    {\n                      \"id\": 472,\n                      \"name\": \"conversationState\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"(Optional) A ConversationState instance to use in the test client\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"ConversationState\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 462,\n                    \"name\": \"BotkitTestClient\"\n                  }\n                },\n                {\n                  \"id\": 473,\n                  \"name\": \"new BotkitTestClient\",\n                  \"kind\": 16384,\n                  \"kindString\": \"Constructor signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Create a BotkitTestClient to test a dialog without having to create a full-fledged adapter.\",\n                    \"text\": \"```javascript\\nlet client = new BotkitTestClient('test', bot, MY_DIALOG, MY_OPTIONS);\\nlet reply = await client.sendActivity('first message');\\nassert.strictEqual(reply.text, 'first reply', 'reply failed');\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 474,\n                      \"name\": \"testAdapter\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"TestAdapter\"\n                      }\n                    },\n                    {\n                      \"id\": 475,\n                      \"name\": \"bot\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"(Required) The Botkit bot that has the skill to test.\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 185,\n                        \"name\": \"Botkit\"\n                      }\n                    },\n                    {\n                      \"id\": 476,\n                      \"name\": \"dialogToTest\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"(Required) The identifier of the skill to test in the bot.\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          },\n                          {\n                            \"type\": \"array\",\n                            \"elementType\": {\n                              \"type\": \"intrinsic\",\n                              \"name\": \"string\"\n                            }\n                          }\n                        ]\n                      }\n                    },\n                    {\n                      \"id\": 477,\n                      \"name\": \"initialDialogOptions\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"(Optional) additional argument(s) to pass to the dialog being started.\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 478,\n                      \"name\": \"middlewares\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"(Optional) a stack of middleware to be run when testing\"\n                      },\n                      \"type\": {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"reference\",\n                          \"name\": \"Middleware\"\n                        }\n                      }\n                    },\n                    {\n                      \"id\": 479,\n                      \"name\": \"conversationState\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"(Optional) A ConversationState instance to use in the test client\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"ConversationState\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 462,\n                    \"name\": \"BotkitTestClient\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"testClient.ts\",\n                  \"line\": 27,\n                  \"character\": 48\n                },\n                {\n                  \"fileName\": \"testClient.ts\",\n                  \"line\": 47,\n                  \"character\": 182\n                },\n                {\n                  \"fileName\": \"testClient.ts\",\n                  \"line\": 48,\n                  \"character\": 189\n                }\n              ]\n            },\n            {\n              \"id\": 464,\n              \"name\": \"conversationState\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"testClient.ts\",\n                  \"line\": 27,\n                  \"character\": 28\n                }\n              ],\n              \"type\": {\n                \"type\": \"reference\",\n                \"name\": \"ConversationState\"\n              }\n            },\n            {\n              \"id\": 463,\n              \"name\": \"dialogTurnResult\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"testClient.ts\",\n                  \"line\": 26,\n                  \"character\": 27\n                }\n              ],\n              \"type\": {\n                \"type\": \"reference\",\n                \"name\": \"DialogTurnResult\"\n              }\n            },\n            {\n              \"id\": 483,\n              \"name\": \"getNextReply\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 484,\n                  \"name\": \"getNextReply\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Get the next reply waiting to be delivered (if one exists)\"\n                  },\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"reference\",\n                        \"name\": \"Activity\"\n                      }\n                    ],\n                    \"name\": \"Partial\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"testClient.ts\",\n                  \"line\": 104,\n                  \"character\": 23\n                }\n              ]\n            },\n            {\n              \"id\": 480,\n              \"name\": \"sendActivity\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 481,\n                  \"name\": \"sendActivity\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Send an activity into the dialog.\",\n                    \"returns\": \"a TestFlow that can be used to assert replies etc\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 482,\n                      \"name\": \"activity\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"an activity potentially with text\\n\\n```javascript\\nDialogTest.send('hello').assertReply('hello yourself').then(done);\\n```\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"reference\",\n                            \"typeArguments\": [\n                              {\n                                \"type\": \"reference\",\n                                \"name\": \"Activity\"\n                              }\n                            ],\n                            \"name\": \"Partial\"\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        ]\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"testClient.ts\",\n                  \"line\": 96,\n                  \"character\": 29\n                }\n              ]\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Constructors\",\n              \"kind\": 512,\n              \"children\": [\n                465\n              ]\n            },\n            {\n              \"title\": \"Properties\",\n              \"kind\": 1024,\n              \"children\": [\n                464,\n                463\n              ]\n            },\n            {\n              \"title\": \"Methods\",\n              \"kind\": 2048,\n              \"children\": [\n                483,\n                480\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"testClient.ts\",\n              \"line\": 23,\n              \"character\": 29\n            }\n          ],\n          \"props\": [\n            {\n              \"id\": 464,\n              \"name\": \"conversationState\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"testClient.ts\",\n                  \"line\": 27,\n                  \"character\": 28\n                }\n              ],\n              \"type\": {\n                \"type\": \"reference\",\n                \"name\": \"ConversationState\"\n              }\n            },\n            {\n              \"id\": 463,\n              \"name\": \"dialogTurnResult\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"testClient.ts\",\n                  \"line\": 26,\n                  \"character\": 27\n                }\n              ],\n              \"type\": {\n                \"type\": \"reference\",\n                \"name\": \"DialogTurnResult\"\n              }\n            }\n          ],\n          \"methods\": [\n            {\n              \"id\": 483,\n              \"name\": \"getNextReply\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 484,\n                  \"name\": \"getNextReply\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Get the next reply waiting to be delivered (if one exists)\"\n                  },\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"reference\",\n                        \"name\": \"Activity\"\n                      }\n                    ],\n                    \"name\": \"Partial\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"testClient.ts\",\n                  \"line\": 104,\n                  \"character\": 23\n                }\n              ]\n            },\n            {\n              \"id\": 480,\n              \"name\": \"sendActivity\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 481,\n                  \"name\": \"sendActivity\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Send an activity into the dialog.\",\n                    \"returns\": \"a TestFlow that can be used to assert replies etc\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 482,\n                      \"name\": \"activity\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"an activity potentially with text\\n\\n```javascript\\nDialogTest.send('hello').assertReply('hello yourself').then(done);\\n```\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"reference\",\n                            \"typeArguments\": [\n                              {\n                                \"type\": \"reference\",\n                                \"name\": \"Activity\"\n                              }\n                            ],\n                            \"name\": \"Partial\"\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        ]\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"testClient.ts\",\n                  \"line\": 96,\n                  \"character\": 29\n                }\n              ]\n            }\n          ],\n          \"constructors\": [\n            {\n              \"id\": 465,\n              \"name\": \"constructor\",\n              \"kind\": 512,\n              \"kindString\": \"Constructor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Create a BotkitTestClient to test a dialog without having to create a full-fledged adapter.\",\n                \"text\": \"```javascript\\nlet client = new BotkitTestClient('test', bot, MY_DIALOG, MY_OPTIONS);\\nlet reply = await client.sendActivity('first message');\\nassert.strictEqual(reply.text, 'first reply', 'reply failed');\\n```\\n\"\n              },\n              \"signatures\": [\n                {\n                  \"id\": 466,\n                  \"name\": \"new BotkitTestClient\",\n                  \"kind\": 16384,\n                  \"kindString\": \"Constructor signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Create a BotkitTestClient to test a dialog without having to create a full-fledged adapter.\",\n                    \"text\": \"```javascript\\nlet client = new BotkitTestClient('test', bot, MY_DIALOG, MY_OPTIONS);\\nlet reply = await client.sendActivity('first message');\\nassert.strictEqual(reply.text, 'first reply', 'reply failed');\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 467,\n                      \"name\": \"channelId\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"The channelId to be used for the test.\\nUse 'emulator' or 'test' if you are uncertain of the channel you are targeting.\\nOtherwise, it is recommended that you use the id for the channel(s) your bot will be using and write a test case for each channel.\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 468,\n                      \"name\": \"bot\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"(Required) The Botkit bot that has the skill to test.\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 185,\n                        \"name\": \"Botkit\"\n                      }\n                    },\n                    {\n                      \"id\": 469,\n                      \"name\": \"dialogToTest\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"(Required) The identifier of the skill to test in the bot.\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          },\n                          {\n                            \"type\": \"array\",\n                            \"elementType\": {\n                              \"type\": \"intrinsic\",\n                              \"name\": \"string\"\n                            }\n                          }\n                        ]\n                      }\n                    },\n                    {\n                      \"id\": 470,\n                      \"name\": \"initialDialogOptions\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"(Optional) additional argument(s) to pass to the dialog being started.\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 471,\n                      \"name\": \"middlewares\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"(Optional) a stack of middleware to be run when testing\"\n                      },\n                      \"type\": {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"reference\",\n                          \"name\": \"Middleware\"\n                        }\n                      }\n                    },\n                    {\n                      \"id\": 472,\n                      \"name\": \"conversationState\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"(Optional) A ConversationState instance to use in the test client\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"ConversationState\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 462,\n                    \"name\": \"BotkitTestClient\"\n                  }\n                },\n                {\n                  \"id\": 473,\n                  \"name\": \"new BotkitTestClient\",\n                  \"kind\": 16384,\n                  \"kindString\": \"Constructor signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Create a BotkitTestClient to test a dialog without having to create a full-fledged adapter.\",\n                    \"text\": \"```javascript\\nlet client = new BotkitTestClient('test', bot, MY_DIALOG, MY_OPTIONS);\\nlet reply = await client.sendActivity('first message');\\nassert.strictEqual(reply.text, 'first reply', 'reply failed');\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 474,\n                      \"name\": \"testAdapter\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"TestAdapter\"\n                      }\n                    },\n                    {\n                      \"id\": 475,\n                      \"name\": \"bot\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"(Required) The Botkit bot that has the skill to test.\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 185,\n                        \"name\": \"Botkit\"\n                      }\n                    },\n                    {\n                      \"id\": 476,\n                      \"name\": \"dialogToTest\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"(Required) The identifier of the skill to test in the bot.\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          },\n                          {\n                            \"type\": \"array\",\n                            \"elementType\": {\n                              \"type\": \"intrinsic\",\n                              \"name\": \"string\"\n                            }\n                          }\n                        ]\n                      }\n                    },\n                    {\n                      \"id\": 477,\n                      \"name\": \"initialDialogOptions\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"(Optional) additional argument(s) to pass to the dialog being started.\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 478,\n                      \"name\": \"middlewares\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"(Optional) a stack of middleware to be run when testing\"\n                      },\n                      \"type\": {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"reference\",\n                          \"name\": \"Middleware\"\n                        }\n                      }\n                    },\n                    {\n                      \"id\": 479,\n                      \"name\": \"conversationState\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"(Optional) A ConversationState instance to use in the test client\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"ConversationState\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 462,\n                    \"name\": \"BotkitTestClient\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"testClient.ts\",\n                  \"line\": 27,\n                  \"character\": 48\n                },\n                {\n                  \"fileName\": \"testClient.ts\",\n                  \"line\": 47,\n                  \"character\": 182\n                },\n                {\n                  \"fileName\": \"testClient.ts\",\n                  \"line\": 48,\n                  \"character\": 189\n                }\n              ]\n            }\n          ]\n        },\n        {\n          \"id\": 106,\n          \"name\": \"TeamsInvokeMiddleware\",\n          \"kind\": 128,\n          \"kindString\": \"Class\",\n          \"flags\": {\n            \"isExported\": true,\n            \"isExternal\": true\n          },\n          \"comment\": {\n            \"shortText\": \"When used, causes Botkit to emit special events for teams \\\"invokes\\\"\\nBased on https://github.com/microsoft/botbuilder-js/blob/master/libraries/botbuilder/src/teamsActivityHandler.ts\\nThis allows Botkit bots to respond directly to task/fetch or task/submit events, as an example.\\nTo use this, bind it to the adapter before creating the Botkit controller:\\n```javascript\\nconst Botkit = new Botkit({...});\\nbotkit.adapter.use(new TeamsInvokeMiddleware());\",\n            \"text\": \"// can bind directly to task/fetch, task/submit and other invoke types used by teams\\ncontroller.on('task/fetch', async(bot, message) => {\\n   await bot.replyWithTaskInfo(message, taskInfo);\\n});\\n```\\n\"\n          },\n          \"children\": [\n            {\n              \"id\": 107,\n              \"name\": \"onTurn\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 108,\n                  \"name\": \"onTurn\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Not for direct use - implements the MiddlewareSet's required onTurn function used to process the event\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 109,\n                      \"name\": \"context\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"TurnContext\"\n                      }\n                    },\n                    {\n                      \"id\": 110,\n                      \"name\": \"next\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 111,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 112,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"any\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"teamsHelpers.ts\",\n                              \"line\": 79,\n                              \"character\": 51\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"teamsHelpers.ts\",\n                  \"line\": 79,\n                  \"character\": 23\n                }\n              ]\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Methods\",\n              \"kind\": 2048,\n              \"children\": [\n                107\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"teamsHelpers.ts\",\n              \"line\": 73,\n              \"character\": 34\n            }\n          ],\n          \"extendedTypes\": [\n            {\n              \"type\": \"intrinsic\",\n              \"name\": \"any\"\n            }\n          ],\n          \"props\": [],\n          \"methods\": [\n            {\n              \"id\": 107,\n              \"name\": \"onTurn\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 108,\n                  \"name\": \"onTurn\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Not for direct use - implements the MiddlewareSet's required onTurn function used to process the event\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 109,\n                      \"name\": \"context\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"TurnContext\"\n                      }\n                    },\n                    {\n                      \"id\": 110,\n                      \"name\": \"next\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 111,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 112,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"any\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"teamsHelpers.ts\",\n                              \"line\": 79,\n                              \"character\": 51\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"teamsHelpers.ts\",\n                  \"line\": 79,\n                  \"character\": 23\n                }\n              ]\n            }\n          ],\n          \"constructors\": []\n        }\n      ],\n      \"interfaces\": [\n        {\n          \"id\": 137,\n          \"name\": \"BotkitConfiguration\",\n          \"kind\": 256,\n          \"kindString\": \"Interface\",\n          \"flags\": {\n            \"isExported\": true,\n            \"isExternal\": true\n          },\n          \"comment\": {\n            \"shortText\": \"Defines the options used when instantiating Botkit to create the main app controller with `new Botkit(options)`\"\n          },\n          \"children\": [\n            {\n              \"id\": 140,\n              \"name\": \"adapter\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A fully configured BotBuilder Adapter, such as `botbuilder-adapter-slack` or `botbuilder-adapter-web`\\nThe adapter is responsible for translating platform-specific messages into the format understood by Botkit and BotBuilder.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 41,\n                  \"character\": 11\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"any\"\n              }\n            },\n            {\n              \"id\": 141,\n              \"name\": \"adapterConfig\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"If using the BotFramework service, options included in `adapterConfig` will be passed to the new Adapter when created internally.\\nSee [BotFrameworkAdapterSettings](https://docs.microsoft.com/en-us/javascript/api/botbuilder/botframeworkadaptersettings?view=azure-node-latest&viewFallbackFrom=botbuilder-ts-latest).\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 47,\n                  \"character\": 17\n                }\n              ],\n              \"type\": {\n                \"type\": \"reflection\",\n                \"declaration\": {\n                  \"id\": 142,\n                  \"name\": \"__type\",\n                  \"kind\": 65536,\n                  \"kindString\": \"Type literal\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"indexSignature\": [\n                    {\n                      \"id\": 143,\n                      \"name\": \"__index\",\n                      \"kind\": 8192,\n                      \"kindString\": \"Index signature\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"parameters\": [\n                        {\n                          \"id\": 144,\n                          \"name\": \"key\",\n                          \"kind\": 32768,\n                          \"kindString\": \"Parameter\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"type\": {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        }\n                      ],\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"sources\": [\n                    {\n                      \"fileName\": \"core.ts\",\n                      \"line\": 47,\n                      \"character\": 19\n                    }\n                  ]\n                }\n              }\n            },\n            {\n              \"id\": 139,\n              \"name\": \"dialogStateProperty\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Name of the dialogState property in the ConversationState that will be used to automatically track the dialog state. Defaults to `dialogState`.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 35,\n                  \"character\": 23\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 149,\n              \"name\": \"disable_console\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Disable messages normally sent to the console during startup.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 75,\n                  \"character\": 19\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"boolean\"\n              }\n            },\n            {\n              \"id\": 148,\n              \"name\": \"disable_webserver\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Disable webserver. If true, Botkit will not create a webserver or expose any webhook endpoints automatically. Defaults to false.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 70,\n                  \"character\": 21\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"boolean\"\n              }\n            },\n            {\n              \"id\": 150,\n              \"name\": \"jsonLimit\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Limit of the size of incoming JSON payloads parsed by the Express bodyParser. Defaults to '100kb'\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 80,\n                  \"character\": 13\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 147,\n              \"name\": \"storage\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A Storage interface compatible with [this specification](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/storage?view=botbuilder-ts-latest)\\nDefaults to the ephemeral [MemoryStorage](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/memorystorage?view=botbuilder-ts-latest) implementation.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 65,\n                  \"character\": 11\n                }\n              ],\n              \"type\": {\n                \"type\": \"reference\",\n                \"name\": \"Storage\"\n              }\n            },\n            {\n              \"id\": 151,\n              \"name\": \"urlEncodedLimit\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Limit of the size of incoming URL encoded payloads parsed by the Express bodyParser. Defaults to '100kb'\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 85,\n                  \"character\": 19\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 138,\n              \"name\": \"webhook_uri\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Path used to create incoming webhook URI.  Defaults to `/api/messages`\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 30,\n                  \"character\": 15\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 145,\n              \"name\": \"webserver\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"An instance of Express used to define web endpoints.  If not specified, one will be created internally.\\nNote: only use your own Express if you absolutely must for some reason. Otherwise, use `controller.webserver`\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 53,\n                  \"character\": 13\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"any\"\n              }\n            },\n            {\n              \"id\": 146,\n              \"name\": \"webserver_middlewares\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"An array of middlewares that will be automatically bound to the webserver.\\nShould be in the form (req, res, next) => {}\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 59,\n                  \"character\": 25\n                }\n              ],\n              \"type\": {\n                \"type\": \"array\",\n                \"elementType\": {\n                  \"type\": \"intrinsic\",\n                  \"name\": \"any\"\n                }\n              }\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Properties\",\n              \"kind\": 1024,\n              \"children\": [\n                140,\n                141,\n                139,\n                149,\n                148,\n                150,\n                147,\n                151,\n                138,\n                145,\n                146\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"core.ts\",\n              \"line\": 26,\n              \"character\": 36\n            }\n          ],\n          \"props\": [\n            {\n              \"id\": 140,\n              \"name\": \"adapter\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A fully configured BotBuilder Adapter, such as `botbuilder-adapter-slack` or `botbuilder-adapter-web`\\nThe adapter is responsible for translating platform-specific messages into the format understood by Botkit and BotBuilder.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 41,\n                  \"character\": 11\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"any\"\n              }\n            },\n            {\n              \"id\": 141,\n              \"name\": \"adapterConfig\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"If using the BotFramework service, options included in `adapterConfig` will be passed to the new Adapter when created internally.\\nSee [BotFrameworkAdapterSettings](https://docs.microsoft.com/en-us/javascript/api/botbuilder/botframeworkadaptersettings?view=azure-node-latest&viewFallbackFrom=botbuilder-ts-latest).\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 47,\n                  \"character\": 17\n                }\n              ],\n              \"type\": {\n                \"type\": \"reflection\",\n                \"declaration\": {\n                  \"id\": 142,\n                  \"name\": \"__type\",\n                  \"kind\": 65536,\n                  \"kindString\": \"Type literal\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"indexSignature\": [\n                    {\n                      \"id\": 143,\n                      \"name\": \"__index\",\n                      \"kind\": 8192,\n                      \"kindString\": \"Index signature\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"parameters\": [\n                        {\n                          \"id\": 144,\n                          \"name\": \"key\",\n                          \"kind\": 32768,\n                          \"kindString\": \"Parameter\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"type\": {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        }\n                      ],\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"sources\": [\n                    {\n                      \"fileName\": \"core.ts\",\n                      \"line\": 47,\n                      \"character\": 19\n                    }\n                  ]\n                }\n              }\n            },\n            {\n              \"id\": 139,\n              \"name\": \"dialogStateProperty\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Name of the dialogState property in the ConversationState that will be used to automatically track the dialog state. Defaults to `dialogState`.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 35,\n                  \"character\": 23\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 149,\n              \"name\": \"disable_console\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Disable messages normally sent to the console during startup.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 75,\n                  \"character\": 19\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"boolean\"\n              }\n            },\n            {\n              \"id\": 148,\n              \"name\": \"disable_webserver\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Disable webserver. If true, Botkit will not create a webserver or expose any webhook endpoints automatically. Defaults to false.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 70,\n                  \"character\": 21\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"boolean\"\n              }\n            },\n            {\n              \"id\": 150,\n              \"name\": \"jsonLimit\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Limit of the size of incoming JSON payloads parsed by the Express bodyParser. Defaults to '100kb'\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 80,\n                  \"character\": 13\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 147,\n              \"name\": \"storage\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A Storage interface compatible with [this specification](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/storage?view=botbuilder-ts-latest)\\nDefaults to the ephemeral [MemoryStorage](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/memorystorage?view=botbuilder-ts-latest) implementation.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 65,\n                  \"character\": 11\n                }\n              ],\n              \"type\": {\n                \"type\": \"reference\",\n                \"name\": \"Storage\"\n              }\n            },\n            {\n              \"id\": 151,\n              \"name\": \"urlEncodedLimit\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Limit of the size of incoming URL encoded payloads parsed by the Express bodyParser. Defaults to '100kb'\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 85,\n                  \"character\": 19\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 138,\n              \"name\": \"webhook_uri\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Path used to create incoming webhook URI.  Defaults to `/api/messages`\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 30,\n                  \"character\": 15\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 145,\n              \"name\": \"webserver\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"An instance of Express used to define web endpoints.  If not specified, one will be created internally.\\nNote: only use your own Express if you absolutely must for some reason. Otherwise, use `controller.webserver`\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 53,\n                  \"character\": 13\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"any\"\n              }\n            },\n            {\n              \"id\": 146,\n              \"name\": \"webserver_middlewares\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"An array of middlewares that will be automatically bound to the webserver.\\nShould be in the form (req, res, next) => {}\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 59,\n                  \"character\": 25\n                }\n              ],\n              \"type\": {\n                \"type\": \"array\",\n                \"elementType\": {\n                  \"type\": \"intrinsic\",\n                  \"name\": \"any\"\n                }\n              }\n            }\n          ]\n        },\n        {\n          \"id\": 366,\n          \"name\": \"BotkitConversationStep\",\n          \"kind\": 256,\n          \"kindString\": \"Interface\",\n          \"flags\": {\n            \"isExported\": true,\n            \"isExternal\": true\n          },\n          \"children\": [\n            {\n              \"id\": 367,\n              \"name\": \"index\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"The number pointing to the current message in the current thread in this dialog's script\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 61,\n                  \"character\": 9\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"number\"\n              }\n            },\n            {\n              \"id\": 375,\n              \"name\": \"next\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A function to call when the step is completed.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 93,\n                  \"character\": 8\n                }\n              ],\n              \"type\": {\n                \"type\": \"reflection\",\n                \"declaration\": {\n                  \"id\": 376,\n                  \"name\": \"__type\",\n                  \"kind\": 65536,\n                  \"kindString\": \"Type literal\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"signatures\": [\n                    {\n                      \"id\": 377,\n                      \"name\": \"__call\",\n                      \"kind\": 4096,\n                      \"kindString\": \"Call signature\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"parameters\": [\n                        {\n                          \"id\": 378,\n                          \"name\": \"stepResult\",\n                          \"kind\": 32768,\n                          \"kindString\": \"Parameter\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"type\": {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"any\"\n                          }\n                        }\n                      ],\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"any\"\n                          }\n                        ],\n                        \"name\": \"Promise\"\n                      }\n                    }\n                  ],\n                  \"sources\": [\n                    {\n                      \"fileName\": \"conversation.ts\",\n                      \"line\": 93,\n                      \"character\": 9\n                    }\n                  ]\n                }\n              }\n            },\n            {\n              \"id\": 371,\n              \"name\": \"options\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A pointer to any options passed into the dialog when it began\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 77,\n                  \"character\": 11\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"any\"\n              }\n            },\n            {\n              \"id\": 372,\n              \"name\": \"reason\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"The reason for this step being called\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 81,\n                  \"character\": 10\n                }\n              ],\n              \"type\": {\n                \"type\": \"reference\",\n                \"name\": \"DialogReason\"\n              }\n            },\n            {\n              \"id\": 373,\n              \"name\": \"result\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"The results of the previous turn\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 85,\n                  \"character\": 10\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"any\"\n              }\n            },\n            {\n              \"id\": 370,\n              \"name\": \"state\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A pointer to the current dialog state\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 73,\n                  \"character\": 9\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"any\"\n              }\n            },\n            {\n              \"id\": 368,\n              \"name\": \"thread\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"The name of the current thread\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 65,\n                  \"character\": 10\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 369,\n              \"name\": \"threadLength\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"The length of the current thread\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 69,\n                  \"character\": 16\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"number\"\n              }\n            },\n            {\n              \"id\": 374,\n              \"name\": \"values\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A pointer directly to state.values\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 89,\n                  \"character\": 10\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"any\"\n              }\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Properties\",\n              \"kind\": 1024,\n              \"children\": [\n                367,\n                375,\n                371,\n                372,\n                373,\n                370,\n                368,\n                369,\n                374\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"conversation.ts\",\n              \"line\": 57,\n              \"character\": 39\n            }\n          ],\n          \"props\": [\n            {\n              \"id\": 367,\n              \"name\": \"index\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"The number pointing to the current message in the current thread in this dialog's script\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 61,\n                  \"character\": 9\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"number\"\n              }\n            },\n            {\n              \"id\": 375,\n              \"name\": \"next\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A function to call when the step is completed.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 93,\n                  \"character\": 8\n                }\n              ],\n              \"type\": {\n                \"type\": \"reflection\",\n                \"declaration\": {\n                  \"id\": 376,\n                  \"name\": \"__type\",\n                  \"kind\": 65536,\n                  \"kindString\": \"Type literal\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"signatures\": [\n                    {\n                      \"id\": 377,\n                      \"name\": \"__call\",\n                      \"kind\": 4096,\n                      \"kindString\": \"Call signature\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"parameters\": [\n                        {\n                          \"id\": 378,\n                          \"name\": \"stepResult\",\n                          \"kind\": 32768,\n                          \"kindString\": \"Parameter\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"type\": {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"any\"\n                          }\n                        }\n                      ],\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"any\"\n                          }\n                        ],\n                        \"name\": \"Promise\"\n                      }\n                    }\n                  ],\n                  \"sources\": [\n                    {\n                      \"fileName\": \"conversation.ts\",\n                      \"line\": 93,\n                      \"character\": 9\n                    }\n                  ]\n                }\n              }\n            },\n            {\n              \"id\": 371,\n              \"name\": \"options\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A pointer to any options passed into the dialog when it began\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 77,\n                  \"character\": 11\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"any\"\n              }\n            },\n            {\n              \"id\": 372,\n              \"name\": \"reason\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"The reason for this step being called\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 81,\n                  \"character\": 10\n                }\n              ],\n              \"type\": {\n                \"type\": \"reference\",\n                \"name\": \"DialogReason\"\n              }\n            },\n            {\n              \"id\": 373,\n              \"name\": \"result\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"The results of the previous turn\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 85,\n                  \"character\": 10\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"any\"\n              }\n            },\n            {\n              \"id\": 370,\n              \"name\": \"state\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A pointer to the current dialog state\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 73,\n                  \"character\": 9\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"any\"\n              }\n            },\n            {\n              \"id\": 368,\n              \"name\": \"thread\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"The name of the current thread\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 65,\n                  \"character\": 10\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 369,\n              \"name\": \"threadLength\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"The length of the current thread\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 69,\n                  \"character\": 16\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"number\"\n              }\n            },\n            {\n              \"id\": 374,\n              \"name\": \"values\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A pointer directly to state.values\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 89,\n                  \"character\": 10\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"any\"\n              }\n            }\n          ]\n        },\n        {\n          \"id\": 318,\n          \"name\": \"BotkitConvoHandler\",\n          \"kind\": 256,\n          \"kindString\": \"Interface\",\n          \"flags\": {\n            \"isExternal\": true\n          },\n          \"comment\": {\n            \"shortText\": \"Definition of the handler functions used to handle .ask and .addQuestion conditions\"\n          },\n          \"signatures\": [\n            {\n              \"id\": 319,\n              \"name\": \"__call\",\n              \"kind\": 4096,\n              \"kindString\": \"Call signature\",\n              \"flags\": {},\n              \"comment\": {\n                \"shortText\": \"Definition of the handler functions used to handle .ask and .addQuestion conditions\"\n              },\n              \"parameters\": [\n                {\n                  \"id\": 320,\n                  \"name\": \"answer\",\n                  \"kind\": 32768,\n                  \"kindString\": \"Parameter\",\n                  \"flags\": {},\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"string\"\n                  }\n                },\n                {\n                  \"id\": 321,\n                  \"name\": \"convo\",\n                  \"kind\": 32768,\n                  \"kindString\": \"Parameter\",\n                  \"flags\": {},\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 297,\n                    \"name\": \"BotkitDialogWrapper\"\n                  }\n                },\n                {\n                  \"id\": 322,\n                  \"name\": \"bot\",\n                  \"kind\": 32768,\n                  \"kindString\": \"Parameter\",\n                  \"flags\": {},\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 2,\n                    \"name\": \"BotWorker\"\n                  }\n                },\n                {\n                  \"id\": 323,\n                  \"name\": \"message\",\n                  \"kind\": 32768,\n                  \"kindString\": \"Parameter\",\n                  \"flags\": {},\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 152,\n                    \"name\": \"BotkitMessage\"\n                  }\n                }\n              ],\n              \"type\": {\n                \"type\": \"reference\",\n                \"typeArguments\": [\n                  {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"any\"\n                  }\n                ],\n                \"name\": \"Promise\"\n              }\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"conversation.ts\",\n              \"line\": 21,\n              \"character\": 28\n            }\n          ]\n        },\n        {\n          \"id\": 324,\n          \"name\": \"BotkitConvoTrigger\",\n          \"kind\": 256,\n          \"kindString\": \"Interface\",\n          \"flags\": {\n            \"isExternal\": true\n          },\n          \"comment\": {\n            \"shortText\": \"Definition of the trigger pattern passed into .ask or .addQuestion\"\n          },\n          \"children\": [\n            {\n              \"id\": 328,\n              \"name\": \"default\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 32,\n                  \"character\": 11\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"boolean\"\n              }\n            },\n            {\n              \"id\": 327,\n              \"name\": \"handler\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 31,\n                  \"character\": 11\n                }\n              ],\n              \"type\": {\n                \"type\": \"reference\",\n                \"id\": 318,\n                \"name\": \"BotkitConvoHandler\"\n              }\n            },\n            {\n              \"id\": 326,\n              \"name\": \"pattern\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 30,\n                  \"character\": 11\n                }\n              ],\n              \"type\": {\n                \"type\": \"union\",\n                \"types\": [\n                  {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"string\"\n                  },\n                  {\n                    \"type\": \"reference\",\n                    \"name\": \"RegExp\"\n                  }\n                ]\n              }\n            },\n            {\n              \"id\": 325,\n              \"name\": \"type\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 29,\n                  \"character\": 8\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Properties\",\n              \"kind\": 1024,\n              \"children\": [\n                328,\n                327,\n                326,\n                325\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"conversation.ts\",\n              \"line\": 28,\n              \"character\": 28\n            }\n          ],\n          \"props\": [\n            {\n              \"id\": 328,\n              \"name\": \"default\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 32,\n                  \"character\": 11\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"boolean\"\n              }\n            },\n            {\n              \"id\": 327,\n              \"name\": \"handler\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 31,\n                  \"character\": 11\n                }\n              ],\n              \"type\": {\n                \"type\": \"reference\",\n                \"id\": 318,\n                \"name\": \"BotkitConvoHandler\"\n              }\n            },\n            {\n              \"id\": 326,\n              \"name\": \"pattern\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 30,\n                  \"character\": 11\n                }\n              ],\n              \"type\": {\n                \"type\": \"union\",\n                \"types\": [\n                  {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"string\"\n                  },\n                  {\n                    \"type\": \"reference\",\n                    \"name\": \"RegExp\"\n                  }\n                ]\n              }\n            },\n            {\n              \"id\": 325,\n              \"name\": \"type\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 29,\n                  \"character\": 8\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            }\n          ]\n        },\n        {\n          \"id\": 162,\n          \"name\": \"BotkitHandler\",\n          \"kind\": 256,\n          \"kindString\": \"Interface\",\n          \"flags\": {\n            \"isExported\": true,\n            \"isExternal\": true\n          },\n          \"comment\": {\n            \"shortText\": \"A handler function passed into `hears()` or `on()` that receives a [BotWorker](#botworker) instance and a [BotkitMessage](#botkitmessage).  Should be defined as an async function and/or return a Promise.\",\n            \"text\": \"The form of these handlers should be:\\n```javascript\\nasync (bot, message) => {\\n// stuff.\\n}\\n```\\n\\nFor example:\\n```javascript\\ncontroller.on('event', async(bot, message) => {\\n // do somethign using bot and message like...\\n await bot.reply(message,'Received an event.');\\n});\\n```\\n\"\n          },\n          \"signatures\": [\n            {\n              \"id\": 163,\n              \"name\": \"__call\",\n              \"kind\": 4096,\n              \"kindString\": \"Call signature\",\n              \"flags\": {\n                \"isExported\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A handler function passed into `hears()` or `on()` that receives a [BotWorker](#botworker) instance and a [BotkitMessage](#botkitmessage).  Should be defined as an async function and/or return a Promise.\",\n                \"text\": \"The form of these handlers should be:\\n```javascript\\nasync (bot, message) => {\\n// stuff.\\n}\\n```\\n\\nFor example:\\n```javascript\\ncontroller.on('event', async(bot, message) => {\\n // do somethign using bot and message like...\\n await bot.reply(message,'Received an event.');\\n});\\n```\\n\"\n              },\n              \"parameters\": [\n                {\n                  \"id\": 164,\n                  \"name\": \"bot\",\n                  \"kind\": 32768,\n                  \"kindString\": \"Parameter\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 2,\n                    \"name\": \"BotWorker\"\n                  }\n                },\n                {\n                  \"id\": 165,\n                  \"name\": \"message\",\n                  \"kind\": 32768,\n                  \"kindString\": \"Parameter\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 152,\n                    \"name\": \"BotkitMessage\"\n                  }\n                }\n              ],\n              \"type\": {\n                \"type\": \"reference\",\n                \"typeArguments\": [\n                  {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"any\"\n                  }\n                ],\n                \"name\": \"Promise\"\n              }\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"core.ts\",\n              \"line\": 154,\n              \"character\": 30\n            }\n          ]\n        },\n        {\n          \"id\": 152,\n          \"name\": \"BotkitMessage\",\n          \"kind\": 256,\n          \"kindString\": \"Interface\",\n          \"flags\": {\n            \"isExported\": true,\n            \"isExternal\": true\n          },\n          \"comment\": {\n            \"shortText\": \"Defines the expected form of a message or event object being handled by Botkit.\\nWill also contain any additional fields including in the incoming payload.\"\n          },\n          \"indexSignature\": [\n            {\n              \"id\": 160,\n              \"name\": \"__index\",\n              \"kind\": 8192,\n              \"kindString\": \"Index signature\",\n              \"flags\": {\n                \"isExported\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Any additional fields found in the incoming payload from the messaging platform.\"\n              },\n              \"parameters\": [\n                {\n                  \"id\": 161,\n                  \"name\": \"key\",\n                  \"kind\": 32768,\n                  \"kindString\": \"Parameter\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"string\"\n                  }\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"any\"\n              }\n            }\n          ],\n          \"children\": [\n            {\n              \"id\": 157,\n              \"name\": \"channel\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Unique identifier of the room/channel/space in which the message was sent. Typically contains the platform specific designator for that channel.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 117,\n                  \"character\": 11\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 159,\n              \"name\": \"incoming_message\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"The original incoming [BotBuilder Activity](https://docs.microsoft.com/en-us/javascript/api/botframework-schema/activity?view=botbuilder-ts-latest) object as created by the adapter.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 128,\n                  \"character\": 20\n                }\n              ],\n              \"type\": {\n                \"type\": \"reference\",\n                \"name\": \"Activity\"\n              }\n            },\n            {\n              \"id\": 158,\n              \"name\": \"reference\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A full [ConversationReference](https://docs.microsoft.com/en-us/javascript/api/botframework-schema/conversationreference?view=botbuilder-ts-latest) object that defines the address of the message and all information necessary to send messages back to the originating location.\\nCan be stored for later use, and used with [bot.changeContext()](#changeContext) to send proactive messages.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 123,\n                  \"character\": 13\n                }\n              ],\n              \"type\": {\n                \"type\": \"reference\",\n                \"name\": \"ConversationReference\"\n              }\n            },\n            {\n              \"id\": 154,\n              \"name\": \"text\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Text of the message sent by the user (or primary value in case of button click)\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 102,\n                  \"character\": 8\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 153,\n              \"name\": \"type\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"The type of event, in most cases defined by the messaging channel or adapter\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 97,\n                  \"character\": 8\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 156,\n              \"name\": \"user\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Unique identifier of user who sent the message. Typically contains the platform specific user id.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 112,\n                  \"character\": 8\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 155,\n              \"name\": \"value\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Any value field received from the platform\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 107,\n                  \"character\": 9\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Properties\",\n              \"kind\": 1024,\n              \"children\": [\n                157,\n                159,\n                158,\n                154,\n                153,\n                156,\n                155\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"core.ts\",\n              \"line\": 93,\n              \"character\": 30\n            }\n          ],\n          \"props\": [\n            {\n              \"id\": 157,\n              \"name\": \"channel\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Unique identifier of the room/channel/space in which the message was sent. Typically contains the platform specific designator for that channel.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 117,\n                  \"character\": 11\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 159,\n              \"name\": \"incoming_message\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"The original incoming [BotBuilder Activity](https://docs.microsoft.com/en-us/javascript/api/botframework-schema/activity?view=botbuilder-ts-latest) object as created by the adapter.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 128,\n                  \"character\": 20\n                }\n              ],\n              \"type\": {\n                \"type\": \"reference\",\n                \"name\": \"Activity\"\n              }\n            },\n            {\n              \"id\": 158,\n              \"name\": \"reference\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A full [ConversationReference](https://docs.microsoft.com/en-us/javascript/api/botframework-schema/conversationreference?view=botbuilder-ts-latest) object that defines the address of the message and all information necessary to send messages back to the originating location.\\nCan be stored for later use, and used with [bot.changeContext()](#changeContext) to send proactive messages.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 123,\n                  \"character\": 13\n                }\n              ],\n              \"type\": {\n                \"type\": \"reference\",\n                \"name\": \"ConversationReference\"\n              }\n            },\n            {\n              \"id\": 154,\n              \"name\": \"text\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Text of the message sent by the user (or primary value in case of button click)\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 102,\n                  \"character\": 8\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 153,\n              \"name\": \"type\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"The type of event, in most cases defined by the messaging channel or adapter\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 97,\n                  \"character\": 8\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 156,\n              \"name\": \"user\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Unique identifier of user who sent the message. Typically contains the platform specific user id.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 112,\n                  \"character\": 8\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 155,\n              \"name\": \"value\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Any value field received from the platform\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 107,\n                  \"character\": 9\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            }\n          ]\n        },\n        {\n          \"id\": 329,\n          \"name\": \"BotkitMessageTemplate\",\n          \"kind\": 256,\n          \"kindString\": \"Interface\",\n          \"flags\": {\n            \"isExternal\": true\n          },\n          \"comment\": {\n            \"shortText\": \"Template for definiting a BotkitConversation template\"\n          },\n          \"children\": [\n            {\n              \"id\": 335,\n              \"name\": \"action\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 40,\n                  \"character\": 10\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 355,\n              \"name\": \"attachment\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 48,\n                  \"character\": 14\n                }\n              ],\n              \"type\": {\n                \"type\": \"union\",\n                \"types\": [\n                  {\n                    \"type\": \"reflection\",\n                    \"declaration\": {\n                      \"id\": 356,\n                      \"name\": \"__type\",\n                      \"kind\": 65536,\n                      \"kindString\": \"Type literal\",\n                      \"flags\": {},\n                      \"signatures\": [\n                        {\n                          \"id\": 357,\n                          \"name\": \"__call\",\n                          \"kind\": 4096,\n                          \"kindString\": \"Call signature\",\n                          \"flags\": {},\n                          \"parameters\": [\n                            {\n                              \"id\": 358,\n                              \"name\": \"template\",\n                              \"kind\": 32768,\n                              \"kindString\": \"Parameter\",\n                              \"flags\": {},\n                              \"type\": {\n                                \"type\": \"intrinsic\",\n                                \"name\": \"any\"\n                              }\n                            },\n                            {\n                              \"id\": 359,\n                              \"name\": \"vars\",\n                              \"kind\": 32768,\n                              \"kindString\": \"Parameter\",\n                              \"flags\": {},\n                              \"type\": {\n                                \"type\": \"intrinsic\",\n                                \"name\": \"any\"\n                              }\n                            }\n                          ],\n                          \"type\": {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"any\"\n                          }\n                        }\n                      ],\n                      \"sources\": [\n                        {\n                          \"fileName\": \"conversation.ts\",\n                          \"line\": 48,\n                          \"character\": 16\n                        }\n                      ]\n                    }\n                  },\n                  {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"any\"\n                  }\n                ]\n              }\n            },\n            {\n              \"id\": 360,\n              \"name\": \"attachmentLayout\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 49,\n                  \"character\": 20\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 345,\n              \"name\": \"attachments\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 46,\n                  \"character\": 15\n                }\n              ],\n              \"type\": {\n                \"type\": \"union\",\n                \"types\": [\n                  {\n                    \"type\": \"reflection\",\n                    \"declaration\": {\n                      \"id\": 346,\n                      \"name\": \"__type\",\n                      \"kind\": 65536,\n                      \"kindString\": \"Type literal\",\n                      \"flags\": {},\n                      \"signatures\": [\n                        {\n                          \"id\": 347,\n                          \"name\": \"__call\",\n                          \"kind\": 4096,\n                          \"kindString\": \"Call signature\",\n                          \"flags\": {},\n                          \"parameters\": [\n                            {\n                              \"id\": 348,\n                              \"name\": \"template\",\n                              \"kind\": 32768,\n                              \"kindString\": \"Parameter\",\n                              \"flags\": {},\n                              \"type\": {\n                                \"type\": \"intrinsic\",\n                                \"name\": \"any\"\n                              }\n                            },\n                            {\n                              \"id\": 349,\n                              \"name\": \"vars\",\n                              \"kind\": 32768,\n                              \"kindString\": \"Parameter\",\n                              \"flags\": {},\n                              \"type\": {\n                                \"type\": \"intrinsic\",\n                                \"name\": \"any\"\n                              }\n                            }\n                          ],\n                          \"type\": {\n                            \"type\": \"array\",\n                            \"elementType\": {\n                              \"type\": \"intrinsic\",\n                              \"name\": \"any\"\n                            }\n                          }\n                        }\n                      ],\n                      \"sources\": [\n                        {\n                          \"fileName\": \"conversation.ts\",\n                          \"line\": 46,\n                          \"character\": 17\n                        }\n                      ]\n                    }\n                  },\n                  {\n                    \"type\": \"array\",\n                    \"elementType\": {\n                      \"type\": \"intrinsic\",\n                      \"name\": \"any\"\n                    }\n                  }\n                ]\n              }\n            },\n            {\n              \"id\": 350,\n              \"name\": \"blocks\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 47,\n                  \"character\": 10\n                }\n              ],\n              \"type\": {\n                \"type\": \"union\",\n                \"types\": [\n                  {\n                    \"type\": \"reflection\",\n                    \"declaration\": {\n                      \"id\": 351,\n                      \"name\": \"__type\",\n                      \"kind\": 65536,\n                      \"kindString\": \"Type literal\",\n                      \"flags\": {},\n                      \"signatures\": [\n                        {\n                          \"id\": 352,\n                          \"name\": \"__call\",\n                          \"kind\": 4096,\n                          \"kindString\": \"Call signature\",\n                          \"flags\": {},\n                          \"parameters\": [\n                            {\n                              \"id\": 353,\n                              \"name\": \"template\",\n                              \"kind\": 32768,\n                              \"kindString\": \"Parameter\",\n                              \"flags\": {},\n                              \"type\": {\n                                \"type\": \"intrinsic\",\n                                \"name\": \"any\"\n                              }\n                            },\n                            {\n                              \"id\": 354,\n                              \"name\": \"vars\",\n                              \"kind\": 32768,\n                              \"kindString\": \"Parameter\",\n                              \"flags\": {},\n                              \"type\": {\n                                \"type\": \"intrinsic\",\n                                \"name\": \"any\"\n                              }\n                            }\n                          ],\n                          \"type\": {\n                            \"type\": \"array\",\n                            \"elementType\": {\n                              \"type\": \"intrinsic\",\n                              \"name\": \"any\"\n                            }\n                          }\n                        }\n                      ],\n                      \"sources\": [\n                        {\n                          \"fileName\": \"conversation.ts\",\n                          \"line\": 47,\n                          \"character\": 12\n                        }\n                      ]\n                    }\n                  },\n                  {\n                    \"type\": \"array\",\n                    \"elementType\": {\n                      \"type\": \"intrinsic\",\n                      \"name\": \"any\"\n                    }\n                  }\n                ]\n              }\n            },\n            {\n              \"id\": 361,\n              \"name\": \"channelData\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 50,\n                  \"character\": 15\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"any\"\n              }\n            },\n            {\n              \"id\": 362,\n              \"name\": \"collect\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 51,\n                  \"character\": 11\n                }\n              ],\n              \"type\": {\n                \"type\": \"reflection\",\n                \"declaration\": {\n                  \"id\": 363,\n                  \"name\": \"__type\",\n                  \"kind\": 65536,\n                  \"kindString\": \"Type literal\",\n                  \"flags\": {},\n                  \"children\": [\n                    {\n                      \"id\": 364,\n                      \"name\": \"key\",\n                      \"kind\": 32,\n                      \"kindString\": \"Variable\",\n                      \"flags\": {\n                        \"isExternal\": true,\n                        \"isOptional\": true\n                      },\n                      \"sources\": [\n                        {\n                          \"fileName\": \"conversation.ts\",\n                          \"line\": 52,\n                          \"character\": 11\n                        }\n                      ],\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 365,\n                      \"name\": \"options\",\n                      \"kind\": 32,\n                      \"kindString\": \"Variable\",\n                      \"flags\": {\n                        \"isExternal\": true,\n                        \"isOptional\": true\n                      },\n                      \"sources\": [\n                        {\n                          \"fileName\": \"conversation.ts\",\n                          \"line\": 53,\n                          \"character\": 15\n                        }\n                      ],\n                      \"type\": {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"reference\",\n                          \"id\": 324,\n                          \"name\": \"BotkitConvoTrigger\"\n                        }\n                      }\n                    }\n                  ],\n                  \"groups\": [\n                    {\n                      \"title\": \"Variables\",\n                      \"kind\": 32,\n                      \"children\": [\n                        364,\n                        365\n                      ]\n                    }\n                  ],\n                  \"sources\": [\n                    {\n                      \"fileName\": \"conversation.ts\",\n                      \"line\": 51,\n                      \"character\": 12\n                    }\n                  ]\n                }\n              }\n            },\n            {\n              \"id\": 336,\n              \"name\": \"execute\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 41,\n                  \"character\": 11\n                }\n              ],\n              \"type\": {\n                \"type\": \"reflection\",\n                \"declaration\": {\n                  \"id\": 337,\n                  \"name\": \"__type\",\n                  \"kind\": 65536,\n                  \"kindString\": \"Type literal\",\n                  \"flags\": {},\n                  \"children\": [\n                    {\n                      \"id\": 338,\n                      \"name\": \"script\",\n                      \"kind\": 32,\n                      \"kindString\": \"Variable\",\n                      \"flags\": {\n                        \"isExternal\": true\n                      },\n                      \"sources\": [\n                        {\n                          \"fileName\": \"conversation.ts\",\n                          \"line\": 42,\n                          \"character\": 14\n                        }\n                      ],\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 339,\n                      \"name\": \"thread\",\n                      \"kind\": 32,\n                      \"kindString\": \"Variable\",\n                      \"flags\": {\n                        \"isExternal\": true,\n                        \"isOptional\": true\n                      },\n                      \"sources\": [\n                        {\n                          \"fileName\": \"conversation.ts\",\n                          \"line\": 43,\n                          \"character\": 14\n                        }\n                      ],\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"groups\": [\n                    {\n                      \"title\": \"Variables\",\n                      \"kind\": 32,\n                      \"children\": [\n                        338,\n                        339\n                      ]\n                    }\n                  ],\n                  \"sources\": [\n                    {\n                      \"fileName\": \"conversation.ts\",\n                      \"line\": 41,\n                      \"character\": 13\n                    }\n                  ]\n                }\n              }\n            },\n            {\n              \"id\": 340,\n              \"name\": \"quick_replies\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 45,\n                  \"character\": 17\n                }\n              ],\n              \"type\": {\n                \"type\": \"union\",\n                \"types\": [\n                  {\n                    \"type\": \"reflection\",\n                    \"declaration\": {\n                      \"id\": 341,\n                      \"name\": \"__type\",\n                      \"kind\": 65536,\n                      \"kindString\": \"Type literal\",\n                      \"flags\": {},\n                      \"signatures\": [\n                        {\n                          \"id\": 342,\n                          \"name\": \"__call\",\n                          \"kind\": 4096,\n                          \"kindString\": \"Call signature\",\n                          \"flags\": {},\n                          \"parameters\": [\n                            {\n                              \"id\": 343,\n                              \"name\": \"template\",\n                              \"kind\": 32768,\n                              \"kindString\": \"Parameter\",\n                              \"flags\": {},\n                              \"type\": {\n                                \"type\": \"intrinsic\",\n                                \"name\": \"any\"\n                              }\n                            },\n                            {\n                              \"id\": 344,\n                              \"name\": \"vars\",\n                              \"kind\": 32768,\n                              \"kindString\": \"Parameter\",\n                              \"flags\": {},\n                              \"type\": {\n                                \"type\": \"intrinsic\",\n                                \"name\": \"any\"\n                              }\n                            }\n                          ],\n                          \"type\": {\n                            \"type\": \"array\",\n                            \"elementType\": {\n                              \"type\": \"intrinsic\",\n                              \"name\": \"any\"\n                            }\n                          }\n                        }\n                      ],\n                      \"sources\": [\n                        {\n                          \"fileName\": \"conversation.ts\",\n                          \"line\": 45,\n                          \"character\": 19\n                        }\n                      ]\n                    }\n                  },\n                  {\n                    \"type\": \"array\",\n                    \"elementType\": {\n                      \"type\": \"intrinsic\",\n                      \"name\": \"any\"\n                    }\n                  }\n                ]\n              }\n            },\n            {\n              \"id\": 330,\n              \"name\": \"text\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 39,\n                  \"character\": 8\n                }\n              ],\n              \"type\": {\n                \"type\": \"union\",\n                \"types\": [\n                  {\n                    \"type\": \"reflection\",\n                    \"declaration\": {\n                      \"id\": 331,\n                      \"name\": \"__type\",\n                      \"kind\": 65536,\n                      \"kindString\": \"Type literal\",\n                      \"flags\": {},\n                      \"signatures\": [\n                        {\n                          \"id\": 332,\n                          \"name\": \"__call\",\n                          \"kind\": 4096,\n                          \"kindString\": \"Call signature\",\n                          \"flags\": {},\n                          \"parameters\": [\n                            {\n                              \"id\": 333,\n                              \"name\": \"template\",\n                              \"kind\": 32768,\n                              \"kindString\": \"Parameter\",\n                              \"flags\": {},\n                              \"type\": {\n                                \"type\": \"intrinsic\",\n                                \"name\": \"any\"\n                              }\n                            },\n                            {\n                              \"id\": 334,\n                              \"name\": \"vars\",\n                              \"kind\": 32768,\n                              \"kindString\": \"Parameter\",\n                              \"flags\": {},\n                              \"type\": {\n                                \"type\": \"intrinsic\",\n                                \"name\": \"any\"\n                              }\n                            }\n                          ],\n                          \"type\": {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        }\n                      ],\n                      \"sources\": [\n                        {\n                          \"fileName\": \"conversation.ts\",\n                          \"line\": 39,\n                          \"character\": 9\n                        }\n                      ]\n                    }\n                  },\n                  {\n                    \"type\": \"array\",\n                    \"elementType\": {\n                      \"type\": \"intrinsic\",\n                      \"name\": \"string\"\n                    }\n                  }\n                ]\n              }\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Properties\",\n              \"kind\": 1024,\n              \"children\": [\n                335,\n                355,\n                360,\n                345,\n                350,\n                361,\n                362,\n                336,\n                340,\n                330\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"conversation.ts\",\n              \"line\": 38,\n              \"character\": 31\n            }\n          ],\n          \"props\": [\n            {\n              \"id\": 335,\n              \"name\": \"action\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 40,\n                  \"character\": 10\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 355,\n              \"name\": \"attachment\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 48,\n                  \"character\": 14\n                }\n              ],\n              \"type\": {\n                \"type\": \"union\",\n                \"types\": [\n                  {\n                    \"type\": \"reflection\",\n                    \"declaration\": {\n                      \"id\": 356,\n                      \"name\": \"__type\",\n                      \"kind\": 65536,\n                      \"kindString\": \"Type literal\",\n                      \"flags\": {},\n                      \"signatures\": [\n                        {\n                          \"id\": 357,\n                          \"name\": \"__call\",\n                          \"kind\": 4096,\n                          \"kindString\": \"Call signature\",\n                          \"flags\": {},\n                          \"parameters\": [\n                            {\n                              \"id\": 358,\n                              \"name\": \"template\",\n                              \"kind\": 32768,\n                              \"kindString\": \"Parameter\",\n                              \"flags\": {},\n                              \"type\": {\n                                \"type\": \"intrinsic\",\n                                \"name\": \"any\"\n                              }\n                            },\n                            {\n                              \"id\": 359,\n                              \"name\": \"vars\",\n                              \"kind\": 32768,\n                              \"kindString\": \"Parameter\",\n                              \"flags\": {},\n                              \"type\": {\n                                \"type\": \"intrinsic\",\n                                \"name\": \"any\"\n                              }\n                            }\n                          ],\n                          \"type\": {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"any\"\n                          }\n                        }\n                      ],\n                      \"sources\": [\n                        {\n                          \"fileName\": \"conversation.ts\",\n                          \"line\": 48,\n                          \"character\": 16\n                        }\n                      ]\n                    }\n                  },\n                  {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"any\"\n                  }\n                ]\n              }\n            },\n            {\n              \"id\": 360,\n              \"name\": \"attachmentLayout\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 49,\n                  \"character\": 20\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 345,\n              \"name\": \"attachments\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 46,\n                  \"character\": 15\n                }\n              ],\n              \"type\": {\n                \"type\": \"union\",\n                \"types\": [\n                  {\n                    \"type\": \"reflection\",\n                    \"declaration\": {\n                      \"id\": 346,\n                      \"name\": \"__type\",\n                      \"kind\": 65536,\n                      \"kindString\": \"Type literal\",\n                      \"flags\": {},\n                      \"signatures\": [\n                        {\n                          \"id\": 347,\n                          \"name\": \"__call\",\n                          \"kind\": 4096,\n                          \"kindString\": \"Call signature\",\n                          \"flags\": {},\n                          \"parameters\": [\n                            {\n                              \"id\": 348,\n                              \"name\": \"template\",\n                              \"kind\": 32768,\n                              \"kindString\": \"Parameter\",\n                              \"flags\": {},\n                              \"type\": {\n                                \"type\": \"intrinsic\",\n                                \"name\": \"any\"\n                              }\n                            },\n                            {\n                              \"id\": 349,\n                              \"name\": \"vars\",\n                              \"kind\": 32768,\n                              \"kindString\": \"Parameter\",\n                              \"flags\": {},\n                              \"type\": {\n                                \"type\": \"intrinsic\",\n                                \"name\": \"any\"\n                              }\n                            }\n                          ],\n                          \"type\": {\n                            \"type\": \"array\",\n                            \"elementType\": {\n                              \"type\": \"intrinsic\",\n                              \"name\": \"any\"\n                            }\n                          }\n                        }\n                      ],\n                      \"sources\": [\n                        {\n                          \"fileName\": \"conversation.ts\",\n                          \"line\": 46,\n                          \"character\": 17\n                        }\n                      ]\n                    }\n                  },\n                  {\n                    \"type\": \"array\",\n                    \"elementType\": {\n                      \"type\": \"intrinsic\",\n                      \"name\": \"any\"\n                    }\n                  }\n                ]\n              }\n            },\n            {\n              \"id\": 350,\n              \"name\": \"blocks\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 47,\n                  \"character\": 10\n                }\n              ],\n              \"type\": {\n                \"type\": \"union\",\n                \"types\": [\n                  {\n                    \"type\": \"reflection\",\n                    \"declaration\": {\n                      \"id\": 351,\n                      \"name\": \"__type\",\n                      \"kind\": 65536,\n                      \"kindString\": \"Type literal\",\n                      \"flags\": {},\n                      \"signatures\": [\n                        {\n                          \"id\": 352,\n                          \"name\": \"__call\",\n                          \"kind\": 4096,\n                          \"kindString\": \"Call signature\",\n                          \"flags\": {},\n                          \"parameters\": [\n                            {\n                              \"id\": 353,\n                              \"name\": \"template\",\n                              \"kind\": 32768,\n                              \"kindString\": \"Parameter\",\n                              \"flags\": {},\n                              \"type\": {\n                                \"type\": \"intrinsic\",\n                                \"name\": \"any\"\n                              }\n                            },\n                            {\n                              \"id\": 354,\n                              \"name\": \"vars\",\n                              \"kind\": 32768,\n                              \"kindString\": \"Parameter\",\n                              \"flags\": {},\n                              \"type\": {\n                                \"type\": \"intrinsic\",\n                                \"name\": \"any\"\n                              }\n                            }\n                          ],\n                          \"type\": {\n                            \"type\": \"array\",\n                            \"elementType\": {\n                              \"type\": \"intrinsic\",\n                              \"name\": \"any\"\n                            }\n                          }\n                        }\n                      ],\n                      \"sources\": [\n                        {\n                          \"fileName\": \"conversation.ts\",\n                          \"line\": 47,\n                          \"character\": 12\n                        }\n                      ]\n                    }\n                  },\n                  {\n                    \"type\": \"array\",\n                    \"elementType\": {\n                      \"type\": \"intrinsic\",\n                      \"name\": \"any\"\n                    }\n                  }\n                ]\n              }\n            },\n            {\n              \"id\": 361,\n              \"name\": \"channelData\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 50,\n                  \"character\": 15\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"any\"\n              }\n            },\n            {\n              \"id\": 362,\n              \"name\": \"collect\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 51,\n                  \"character\": 11\n                }\n              ],\n              \"type\": {\n                \"type\": \"reflection\",\n                \"declaration\": {\n                  \"id\": 363,\n                  \"name\": \"__type\",\n                  \"kind\": 65536,\n                  \"kindString\": \"Type literal\",\n                  \"flags\": {},\n                  \"children\": [\n                    {\n                      \"id\": 364,\n                      \"name\": \"key\",\n                      \"kind\": 32,\n                      \"kindString\": \"Variable\",\n                      \"flags\": {\n                        \"isExternal\": true,\n                        \"isOptional\": true\n                      },\n                      \"sources\": [\n                        {\n                          \"fileName\": \"conversation.ts\",\n                          \"line\": 52,\n                          \"character\": 11\n                        }\n                      ],\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 365,\n                      \"name\": \"options\",\n                      \"kind\": 32,\n                      \"kindString\": \"Variable\",\n                      \"flags\": {\n                        \"isExternal\": true,\n                        \"isOptional\": true\n                      },\n                      \"sources\": [\n                        {\n                          \"fileName\": \"conversation.ts\",\n                          \"line\": 53,\n                          \"character\": 15\n                        }\n                      ],\n                      \"type\": {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"reference\",\n                          \"id\": 324,\n                          \"name\": \"BotkitConvoTrigger\"\n                        }\n                      }\n                    }\n                  ],\n                  \"groups\": [\n                    {\n                      \"title\": \"Variables\",\n                      \"kind\": 32,\n                      \"children\": [\n                        364,\n                        365\n                      ]\n                    }\n                  ],\n                  \"sources\": [\n                    {\n                      \"fileName\": \"conversation.ts\",\n                      \"line\": 51,\n                      \"character\": 12\n                    }\n                  ]\n                }\n              }\n            },\n            {\n              \"id\": 336,\n              \"name\": \"execute\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 41,\n                  \"character\": 11\n                }\n              ],\n              \"type\": {\n                \"type\": \"reflection\",\n                \"declaration\": {\n                  \"id\": 337,\n                  \"name\": \"__type\",\n                  \"kind\": 65536,\n                  \"kindString\": \"Type literal\",\n                  \"flags\": {},\n                  \"children\": [\n                    {\n                      \"id\": 338,\n                      \"name\": \"script\",\n                      \"kind\": 32,\n                      \"kindString\": \"Variable\",\n                      \"flags\": {\n                        \"isExternal\": true\n                      },\n                      \"sources\": [\n                        {\n                          \"fileName\": \"conversation.ts\",\n                          \"line\": 42,\n                          \"character\": 14\n                        }\n                      ],\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 339,\n                      \"name\": \"thread\",\n                      \"kind\": 32,\n                      \"kindString\": \"Variable\",\n                      \"flags\": {\n                        \"isExternal\": true,\n                        \"isOptional\": true\n                      },\n                      \"sources\": [\n                        {\n                          \"fileName\": \"conversation.ts\",\n                          \"line\": 43,\n                          \"character\": 14\n                        }\n                      ],\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"groups\": [\n                    {\n                      \"title\": \"Variables\",\n                      \"kind\": 32,\n                      \"children\": [\n                        338,\n                        339\n                      ]\n                    }\n                  ],\n                  \"sources\": [\n                    {\n                      \"fileName\": \"conversation.ts\",\n                      \"line\": 41,\n                      \"character\": 13\n                    }\n                  ]\n                }\n              }\n            },\n            {\n              \"id\": 340,\n              \"name\": \"quick_replies\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 45,\n                  \"character\": 17\n                }\n              ],\n              \"type\": {\n                \"type\": \"union\",\n                \"types\": [\n                  {\n                    \"type\": \"reflection\",\n                    \"declaration\": {\n                      \"id\": 341,\n                      \"name\": \"__type\",\n                      \"kind\": 65536,\n                      \"kindString\": \"Type literal\",\n                      \"flags\": {},\n                      \"signatures\": [\n                        {\n                          \"id\": 342,\n                          \"name\": \"__call\",\n                          \"kind\": 4096,\n                          \"kindString\": \"Call signature\",\n                          \"flags\": {},\n                          \"parameters\": [\n                            {\n                              \"id\": 343,\n                              \"name\": \"template\",\n                              \"kind\": 32768,\n                              \"kindString\": \"Parameter\",\n                              \"flags\": {},\n                              \"type\": {\n                                \"type\": \"intrinsic\",\n                                \"name\": \"any\"\n                              }\n                            },\n                            {\n                              \"id\": 344,\n                              \"name\": \"vars\",\n                              \"kind\": 32768,\n                              \"kindString\": \"Parameter\",\n                              \"flags\": {},\n                              \"type\": {\n                                \"type\": \"intrinsic\",\n                                \"name\": \"any\"\n                              }\n                            }\n                          ],\n                          \"type\": {\n                            \"type\": \"array\",\n                            \"elementType\": {\n                              \"type\": \"intrinsic\",\n                              \"name\": \"any\"\n                            }\n                          }\n                        }\n                      ],\n                      \"sources\": [\n                        {\n                          \"fileName\": \"conversation.ts\",\n                          \"line\": 45,\n                          \"character\": 19\n                        }\n                      ]\n                    }\n                  },\n                  {\n                    \"type\": \"array\",\n                    \"elementType\": {\n                      \"type\": \"intrinsic\",\n                      \"name\": \"any\"\n                    }\n                  }\n                ]\n              }\n            },\n            {\n              \"id\": 330,\n              \"name\": \"text\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"conversation.ts\",\n                  \"line\": 39,\n                  \"character\": 8\n                }\n              ],\n              \"type\": {\n                \"type\": \"union\",\n                \"types\": [\n                  {\n                    \"type\": \"reflection\",\n                    \"declaration\": {\n                      \"id\": 331,\n                      \"name\": \"__type\",\n                      \"kind\": 65536,\n                      \"kindString\": \"Type literal\",\n                      \"flags\": {},\n                      \"signatures\": [\n                        {\n                          \"id\": 332,\n                          \"name\": \"__call\",\n                          \"kind\": 4096,\n                          \"kindString\": \"Call signature\",\n                          \"flags\": {},\n                          \"parameters\": [\n                            {\n                              \"id\": 333,\n                              \"name\": \"template\",\n                              \"kind\": 32768,\n                              \"kindString\": \"Parameter\",\n                              \"flags\": {},\n                              \"type\": {\n                                \"type\": \"intrinsic\",\n                                \"name\": \"any\"\n                              }\n                            },\n                            {\n                              \"id\": 334,\n                              \"name\": \"vars\",\n                              \"kind\": 32768,\n                              \"kindString\": \"Parameter\",\n                              \"flags\": {},\n                              \"type\": {\n                                \"type\": \"intrinsic\",\n                                \"name\": \"any\"\n                              }\n                            }\n                          ],\n                          \"type\": {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        }\n                      ],\n                      \"sources\": [\n                        {\n                          \"fileName\": \"conversation.ts\",\n                          \"line\": 39,\n                          \"character\": 9\n                        }\n                      ]\n                    }\n                  },\n                  {\n                    \"type\": \"array\",\n                    \"elementType\": {\n                      \"type\": \"intrinsic\",\n                      \"name\": \"string\"\n                    }\n                  }\n                ]\n              }\n            }\n          ]\n        },\n        {\n          \"id\": 173,\n          \"name\": \"BotkitPlugin\",\n          \"kind\": 256,\n          \"kindString\": \"Interface\",\n          \"flags\": {\n            \"isExported\": true,\n            \"isExternal\": true\n          },\n          \"comment\": {\n            \"shortText\": \"An interface for plugins that can contain multiple middlewares as well as an init function.\"\n          },\n          \"indexSignature\": [\n            {\n              \"id\": 183,\n              \"name\": \"__index\",\n              \"kind\": 8192,\n              \"kindString\": \"Index signature\",\n              \"flags\": {\n                \"isExported\": true\n              },\n              \"comment\": {\n                \"shortText\": \"An interface for plugins that can contain multiple middlewares as well as an init function.\"\n              },\n              \"parameters\": [\n                {\n                  \"id\": 184,\n                  \"name\": \"key\",\n                  \"kind\": 32768,\n                  \"kindString\": \"Parameter\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"string\"\n                  }\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"any\"\n              }\n            }\n          ],\n          \"children\": [\n            {\n              \"id\": 179,\n              \"name\": \"init\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 178,\n                  \"character\": 8\n                }\n              ],\n              \"type\": {\n                \"type\": \"reflection\",\n                \"declaration\": {\n                  \"id\": 180,\n                  \"name\": \"__type\",\n                  \"kind\": 65536,\n                  \"kindString\": \"Type literal\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"signatures\": [\n                    {\n                      \"id\": 181,\n                      \"name\": \"__call\",\n                      \"kind\": 4096,\n                      \"kindString\": \"Call signature\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"parameters\": [\n                        {\n                          \"id\": 182,\n                          \"name\": \"botkit\",\n                          \"kind\": 32768,\n                          \"kindString\": \"Parameter\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"type\": {\n                            \"type\": \"reference\",\n                            \"id\": 185,\n                            \"name\": \"Botkit\"\n                          }\n                        }\n                      ],\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    }\n                  ],\n                  \"sources\": [\n                    {\n                      \"fileName\": \"core.ts\",\n                      \"line\": 178,\n                      \"character\": 10\n                    }\n                  ]\n                }\n              }\n            },\n            {\n              \"id\": 175,\n              \"name\": \"middlewares\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 175,\n                  \"character\": 15\n                }\n              ],\n              \"type\": {\n                \"type\": \"reflection\",\n                \"declaration\": {\n                  \"id\": 176,\n                  \"name\": \"__type\",\n                  \"kind\": 65536,\n                  \"kindString\": \"Type literal\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"indexSignature\": [\n                    {\n                      \"id\": 177,\n                      \"name\": \"__index\",\n                      \"kind\": 8192,\n                      \"kindString\": \"Index signature\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"parameters\": [\n                        {\n                          \"id\": 178,\n                          \"name\": \"key\",\n                          \"kind\": 32768,\n                          \"kindString\": \"Parameter\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"type\": {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        }\n                      ],\n                      \"type\": {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"intrinsic\",\n                          \"name\": \"any\"\n                        }\n                      }\n                    }\n                  ],\n                  \"sources\": [\n                    {\n                      \"fileName\": \"core.ts\",\n                      \"line\": 175,\n                      \"character\": 17\n                    }\n                  ]\n                }\n              }\n            },\n            {\n              \"id\": 174,\n              \"name\": \"name\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 174,\n                  \"character\": 8\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Properties\",\n              \"kind\": 1024,\n              \"children\": [\n                179,\n                175,\n                174\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"core.ts\",\n              \"line\": 173,\n              \"character\": 29\n            }\n          ],\n          \"props\": [\n            {\n              \"id\": 179,\n              \"name\": \"init\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 178,\n                  \"character\": 8\n                }\n              ],\n              \"type\": {\n                \"type\": \"reflection\",\n                \"declaration\": {\n                  \"id\": 180,\n                  \"name\": \"__type\",\n                  \"kind\": 65536,\n                  \"kindString\": \"Type literal\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"signatures\": [\n                    {\n                      \"id\": 181,\n                      \"name\": \"__call\",\n                      \"kind\": 4096,\n                      \"kindString\": \"Call signature\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"parameters\": [\n                        {\n                          \"id\": 182,\n                          \"name\": \"botkit\",\n                          \"kind\": 32768,\n                          \"kindString\": \"Parameter\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"type\": {\n                            \"type\": \"reference\",\n                            \"id\": 185,\n                            \"name\": \"Botkit\"\n                          }\n                        }\n                      ],\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    }\n                  ],\n                  \"sources\": [\n                    {\n                      \"fileName\": \"core.ts\",\n                      \"line\": 178,\n                      \"character\": 10\n                    }\n                  ]\n                }\n              }\n            },\n            {\n              \"id\": 175,\n              \"name\": \"middlewares\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 175,\n                  \"character\": 15\n                }\n              ],\n              \"type\": {\n                \"type\": \"reflection\",\n                \"declaration\": {\n                  \"id\": 176,\n                  \"name\": \"__type\",\n                  \"kind\": 65536,\n                  \"kindString\": \"Type literal\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"indexSignature\": [\n                    {\n                      \"id\": 177,\n                      \"name\": \"__index\",\n                      \"kind\": 8192,\n                      \"kindString\": \"Index signature\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"parameters\": [\n                        {\n                          \"id\": 178,\n                          \"name\": \"key\",\n                          \"kind\": 32768,\n                          \"kindString\": \"Parameter\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"type\": {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        }\n                      ],\n                      \"type\": {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"intrinsic\",\n                          \"name\": \"any\"\n                        }\n                      }\n                    }\n                  ],\n                  \"sources\": [\n                    {\n                      \"fileName\": \"core.ts\",\n                      \"line\": 175,\n                      \"character\": 17\n                    }\n                  ]\n                }\n              }\n            },\n            {\n              \"id\": 174,\n              \"name\": \"name\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 174,\n                  \"character\": 8\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            }\n          ]\n        },\n        {\n          \"id\": 166,\n          \"name\": \"BotkitTrigger\",\n          \"kind\": 256,\n          \"kindString\": \"Interface\",\n          \"flags\": {\n            \"isExternal\": true\n          },\n          \"comment\": {\n            \"shortText\": \"Defines a trigger, including the type, pattern and handler function to fire if triggered.\"\n          },\n          \"children\": [\n            {\n              \"id\": 172,\n              \"name\": \"handler\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 167,\n                  \"character\": 11\n                }\n              ],\n              \"type\": {\n                \"type\": \"reference\",\n                \"id\": 162,\n                \"name\": \"BotkitHandler\"\n              }\n            },\n            {\n              \"id\": 168,\n              \"name\": \"pattern\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 166,\n                  \"character\": 11\n                }\n              ],\n              \"type\": {\n                \"type\": \"union\",\n                \"types\": [\n                  {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"string\"\n                  },\n                  {\n                    \"type\": \"reference\",\n                    \"name\": \"RegExp\"\n                  },\n                  {\n                    \"type\": \"reflection\",\n                    \"declaration\": {\n                      \"id\": 169,\n                      \"name\": \"__type\",\n                      \"kind\": 65536,\n                      \"kindString\": \"Type literal\",\n                      \"flags\": {},\n                      \"signatures\": [\n                        {\n                          \"id\": 170,\n                          \"name\": \"__call\",\n                          \"kind\": 4096,\n                          \"kindString\": \"Call signature\",\n                          \"flags\": {},\n                          \"parameters\": [\n                            {\n                              \"id\": 171,\n                              \"name\": \"message\",\n                              \"kind\": 32768,\n                              \"kindString\": \"Parameter\",\n                              \"flags\": {},\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"id\": 152,\n                                \"name\": \"BotkitMessage\"\n                              }\n                            }\n                          ],\n                          \"type\": {\n                            \"type\": \"reference\",\n                            \"typeArguments\": [\n                              {\n                                \"type\": \"intrinsic\",\n                                \"name\": \"boolean\"\n                              }\n                            ],\n                            \"name\": \"Promise\"\n                          }\n                        }\n                      ],\n                      \"sources\": [\n                        {\n                          \"fileName\": \"core.ts\",\n                          \"line\": 166,\n                          \"character\": 30\n                        }\n                      ]\n                    }\n                  }\n                ]\n              }\n            },\n            {\n              \"id\": 167,\n              \"name\": \"type\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"string, regexp or function\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 165,\n                  \"character\": 8\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Properties\",\n              \"kind\": 1024,\n              \"children\": [\n                172,\n                168,\n                167\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"core.ts\",\n              \"line\": 161,\n              \"character\": 23\n            }\n          ],\n          \"props\": [\n            {\n              \"id\": 172,\n              \"name\": \"handler\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 167,\n                  \"character\": 11\n                }\n              ],\n              \"type\": {\n                \"type\": \"reference\",\n                \"id\": 162,\n                \"name\": \"BotkitHandler\"\n              }\n            },\n            {\n              \"id\": 168,\n              \"name\": \"pattern\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 166,\n                  \"character\": 11\n                }\n              ],\n              \"type\": {\n                \"type\": \"union\",\n                \"types\": [\n                  {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"string\"\n                  },\n                  {\n                    \"type\": \"reference\",\n                    \"name\": \"RegExp\"\n                  },\n                  {\n                    \"type\": \"reflection\",\n                    \"declaration\": {\n                      \"id\": 169,\n                      \"name\": \"__type\",\n                      \"kind\": 65536,\n                      \"kindString\": \"Type literal\",\n                      \"flags\": {},\n                      \"signatures\": [\n                        {\n                          \"id\": 170,\n                          \"name\": \"__call\",\n                          \"kind\": 4096,\n                          \"kindString\": \"Call signature\",\n                          \"flags\": {},\n                          \"parameters\": [\n                            {\n                              \"id\": 171,\n                              \"name\": \"message\",\n                              \"kind\": 32768,\n                              \"kindString\": \"Parameter\",\n                              \"flags\": {},\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"id\": 152,\n                                \"name\": \"BotkitMessage\"\n                              }\n                            }\n                          ],\n                          \"type\": {\n                            \"type\": \"reference\",\n                            \"typeArguments\": [\n                              {\n                                \"type\": \"intrinsic\",\n                                \"name\": \"boolean\"\n                              }\n                            ],\n                            \"name\": \"Promise\"\n                          }\n                        }\n                      ],\n                      \"sources\": [\n                        {\n                          \"fileName\": \"core.ts\",\n                          \"line\": 166,\n                          \"character\": 30\n                        }\n                      ]\n                    }\n                  }\n                ]\n              }\n            },\n            {\n              \"id\": 167,\n              \"name\": \"type\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"string, regexp or function\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"core.ts\",\n                  \"line\": 165,\n                  \"character\": 8\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            }\n          ]\n        }\n      ]\n    },\n    {\n      \"name\": \"Botkit for the Web\",\n      \"packageName\": \"botbuilder-adapter-web\",\n      \"path\": \"reference/web.md\",\n      \"classes\": [\n        {\n          \"id\": 2,\n          \"name\": \"WebAdapter\",\n          \"kind\": 128,\n          \"kindString\": \"Class\",\n          \"flags\": {\n            \"isExported\": true,\n            \"isExternal\": true\n          },\n          \"comment\": {\n            \"shortText\": \"Connect [Botkit](https://www.npmjs.com/package/botkit) or [BotBuilder](https://www.npmjs.com/package/botbuilder) to the Web.\\nIt offers both websocket and webhook capabilities.\\nTo use this adapter, you will need a compatible chat client - generate one using the [Botkit yeoman generator](https://npmjs.com/package/generator-botkit),\\nor use [the one included in the project repo here.](https://github.com/howdyai/botkit/tree/master/packages/botbuilder-adapter-web/client)\"\n          },\n          \"children\": [\n            {\n              \"id\": 5,\n              \"name\": \"constructor\",\n              \"kind\": 512,\n              \"kindString\": \"Constructor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Create an adapter to handle incoming messages from a websocket and/or webhook and translate them into a standard format for processing by your bot.\",\n                \"text\": \"To use with Botkit:\\n```javascript\\nconst adapter = new WebAdapter();\\nconst controller = new Botkit({\\n     adapter: adapter,\\n     // other options\\n});\\n```\\n\\nTo use with BotBuilder:\\n```javascript\\nconst adapter = new WebAdapter();\\nconst server = restify.createServer();\\nserver.use(restify.plugins.bodyParser());\\n// instead of binding processActivity to the incoming request, pass in turn handler logic to createSocketServer\\nlet options = {}; // socket server configuration options\\nadapter.createSocketServer(server, options, async(context) => {\\n // handle turn here\\n});\\n```\\n\"\n              },\n              \"signatures\": [\n                {\n                  \"id\": 6,\n                  \"name\": \"new WebAdapter\",\n                  \"kind\": 16384,\n                  \"kindString\": \"Constructor signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Create an adapter to handle incoming messages from a websocket and/or webhook and translate them into a standard format for processing by your bot.\",\n                    \"text\": \"To use with Botkit:\\n```javascript\\nconst adapter = new WebAdapter();\\nconst controller = new Botkit({\\n     adapter: adapter,\\n     // other options\\n});\\n```\\n\\nTo use with BotBuilder:\\n```javascript\\nconst adapter = new WebAdapter();\\nconst server = restify.createServer();\\nserver.use(restify.plugins.bodyParser());\\n// instead of binding processActivity to the incoming request, pass in turn handler logic to createSocketServer\\nlet options = {}; // socket server configuration options\\nadapter.createSocketServer(server, options, async(context) => {\\n // handle turn here\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 7,\n                      \"name\": \"socketServerOptions\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"an optional object containing parameters to send to a call to [WebSocket.server](https://github.com/websockets/ws/blob/master/doc/ws.md#new-websocketserveroptions-callback).\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 8,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"indexSignature\": [\n                            {\n                              \"id\": 9,\n                              \"name\": \"__index\",\n                              \"kind\": 8192,\n                              \"kindString\": \"Index signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 10,\n                                  \"name\": \"key\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"string\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"intrinsic\",\n                                \"name\": \"any\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"web_adapter.ts\",\n                              \"line\": 64,\n                              \"character\": 44\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 2,\n                    \"name\": \"WebAdapter\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"web_adapter.ts\",\n                  \"line\": 36,\n                  \"character\": 6\n                }\n              ]\n            },\n            {\n              \"id\": 4,\n              \"name\": \"wss\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"The websocket server.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"web_adapter.ts\",\n                  \"line\": 32,\n                  \"character\": 14\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"any\"\n              }\n            },\n            {\n              \"id\": 31,\n              \"name\": \"continueConversation\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 32,\n                  \"name\": \"continueConversation\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Standard BotBuilder adapter method for continuing an existing conversation based on a conversation reference.\\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#continueconversation)\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 33,\n                      \"name\": \"reference\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A conversation reference to be applied to future messages.\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"ConversationReference\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    },\n                    {\n                      \"id\": 34,\n                      \"name\": \"logic\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A bot logic function that will perform continuing action in the form `async(context) => { ... }`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 35,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 36,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 37,\n                                  \"name\": \"context\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"name\": \"TurnContext\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"void\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"web_adapter.ts\",\n                              \"line\": 252,\n                              \"character\": 87\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"web_adapter.ts\",\n                  \"line\": 252,\n                  \"character\": 37\n                }\n              ]\n            },\n            {\n              \"id\": 14,\n              \"name\": \"createSocketServer\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 15,\n                  \"name\": \"createSocketServer\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Bind a websocket listener to an existing webserver object.\\nNote: Create the server using Node's http.createServer\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 16,\n                      \"name\": \"server\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"an http server\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 17,\n                      \"name\": \"socketOptions\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"additional options passed when creating the websocket server with [WebSocket.server](https://github.com/websockets/ws/blob/master/doc/ws.md#new-websocketserveroptions-callback)\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      },\n                      \"defaultValue\": \"{}\"\n                    },\n                    {\n                      \"id\": 18,\n                      \"name\": \"logic\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"a turn handler function in the form `async(context)=>{ ... }` that will handle the bot's logic.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"web_adapter.ts\",\n                  \"line\": 88,\n                  \"character\": 29\n                }\n              ]\n            },\n            {\n              \"id\": 49,\n              \"name\": \"getConnection\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 50,\n                  \"name\": \"getConnection\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Returns websocket connection of given user\\nExample: `if (message.action === 'disconnect') bot.controller.adapter.getConnection(message.user).terminate()`\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 51,\n                      \"name\": \"user\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"name\": \"WebSocket\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"web_adapter.ts\",\n                  \"line\": 327,\n                  \"character\": 24\n                }\n              ]\n            },\n            {\n              \"id\": 11,\n              \"name\": \"init\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 12,\n                  \"name\": \"init\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Botkit-only: Initialization function called automatically when used with Botkit.\\n     * Calls createSocketServer to bind a websocket listener to Botkit's pre-existing webserver.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 13,\n                      \"name\": \"botkit\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"web_adapter.ts\",\n                  \"line\": 74,\n                  \"character\": 15\n                }\n              ]\n            },\n            {\n              \"id\": 46,\n              \"name\": \"isConnected\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 47,\n                  \"name\": \"isConnected\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Is given user currently connected? Use this to test the websocket connection\\nbetween the bot and a given user before sending messages,\\nparticularly in cases where a long period of time may have passed.\",\n                    \"text\": \"Example: `bot.controller.adapter.isConnected(message.user)`\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 48,\n                      \"name\": \"user\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"the id of a user, typically from `message.user`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"boolean\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"web_adapter.ts\",\n                  \"line\": 318,\n                  \"character\": 22\n                }\n              ]\n            },\n            {\n              \"id\": 38,\n              \"name\": \"processActivity\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 39,\n                  \"name\": \"processActivity\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Accept an incoming webhook request and convert it into a TurnContext which can be processed by the bot's logic.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 40,\n                      \"name\": \"req\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A request object from Restify or Express\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 41,\n                      \"name\": \"res\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A response object from Restify or Express\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 42,\n                      \"name\": \"logic\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A bot logic function in the form `async(context) => { ... }`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 43,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 44,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 45,\n                                  \"name\": \"context\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"name\": \"TurnContext\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"void\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"web_adapter.ts\",\n                              \"line\": 269,\n                              \"character\": 49\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"web_adapter.ts\",\n                  \"line\": 269,\n                  \"character\": 32\n                }\n              ]\n            },\n            {\n              \"id\": 19,\n              \"name\": \"sendActivities\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 20,\n                  \"name\": \"sendActivities\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Standard BotBuilder adapter method to send a message from the bot to the messaging API.\\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#sendactivities).\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 21,\n                      \"name\": \"context\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A TurnContext representing the current incoming message and environment. (not used)\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"TurnContext\"\n                      }\n                    },\n                    {\n                      \"id\": 22,\n                      \"name\": \"activities\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An array of outgoing activities to be sent back to the messaging API.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"reference\",\n                          \"typeArguments\": [\n                            {\n                              \"type\": \"reference\",\n                              \"name\": \"Activity\"\n                            }\n                          ],\n                          \"name\": \"Partial\"\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"reference\",\n                          \"name\": \"ResourceResponse\"\n                        }\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"web_adapter.ts\",\n                  \"line\": 193,\n                  \"character\": 31\n                }\n              ]\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Constructors\",\n              \"kind\": 512,\n              \"children\": [\n                5\n              ]\n            },\n            {\n              \"title\": \"Properties\",\n              \"kind\": 1024,\n              \"children\": [\n                4\n              ]\n            },\n            {\n              \"title\": \"Methods\",\n              \"kind\": 2048,\n              \"children\": [\n                31,\n                14,\n                49,\n                11,\n                46,\n                38,\n                19\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"web_adapter.ts\",\n              \"line\": 22,\n              \"character\": 23\n            }\n          ],\n          \"extendedTypes\": [\n            {\n              \"type\": \"intrinsic\",\n              \"name\": \"any\"\n            }\n          ],\n          \"props\": [\n            {\n              \"id\": 4,\n              \"name\": \"wss\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"The websocket server.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"web_adapter.ts\",\n                  \"line\": 32,\n                  \"character\": 14\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"any\"\n              }\n            }\n          ],\n          \"methods\": [\n            {\n              \"id\": 31,\n              \"name\": \"continueConversation\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 32,\n                  \"name\": \"continueConversation\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Standard BotBuilder adapter method for continuing an existing conversation based on a conversation reference.\\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#continueconversation)\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 33,\n                      \"name\": \"reference\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A conversation reference to be applied to future messages.\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"ConversationReference\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    },\n                    {\n                      \"id\": 34,\n                      \"name\": \"logic\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A bot logic function that will perform continuing action in the form `async(context) => { ... }`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 35,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 36,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 37,\n                                  \"name\": \"context\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"name\": \"TurnContext\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"void\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"web_adapter.ts\",\n                              \"line\": 252,\n                              \"character\": 87\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"web_adapter.ts\",\n                  \"line\": 252,\n                  \"character\": 37\n                }\n              ]\n            },\n            {\n              \"id\": 14,\n              \"name\": \"createSocketServer\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 15,\n                  \"name\": \"createSocketServer\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Bind a websocket listener to an existing webserver object.\\nNote: Create the server using Node's http.createServer\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 16,\n                      \"name\": \"server\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"an http server\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 17,\n                      \"name\": \"socketOptions\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"additional options passed when creating the websocket server with [WebSocket.server](https://github.com/websockets/ws/blob/master/doc/ws.md#new-websocketserveroptions-callback)\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      },\n                      \"defaultValue\": \"{}\"\n                    },\n                    {\n                      \"id\": 18,\n                      \"name\": \"logic\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"a turn handler function in the form `async(context)=>{ ... }` that will handle the bot's logic.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"web_adapter.ts\",\n                  \"line\": 88,\n                  \"character\": 29\n                }\n              ]\n            },\n            {\n              \"id\": 49,\n              \"name\": \"getConnection\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 50,\n                  \"name\": \"getConnection\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Returns websocket connection of given user\\nExample: `if (message.action === 'disconnect') bot.controller.adapter.getConnection(message.user).terminate()`\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 51,\n                      \"name\": \"user\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"name\": \"WebSocket\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"web_adapter.ts\",\n                  \"line\": 327,\n                  \"character\": 24\n                }\n              ]\n            },\n            {\n              \"id\": 11,\n              \"name\": \"init\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 12,\n                  \"name\": \"init\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Botkit-only: Initialization function called automatically when used with Botkit.\\n     * Calls createSocketServer to bind a websocket listener to Botkit's pre-existing webserver.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 13,\n                      \"name\": \"botkit\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"web_adapter.ts\",\n                  \"line\": 74,\n                  \"character\": 15\n                }\n              ]\n            },\n            {\n              \"id\": 46,\n              \"name\": \"isConnected\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 47,\n                  \"name\": \"isConnected\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Is given user currently connected? Use this to test the websocket connection\\nbetween the bot and a given user before sending messages,\\nparticularly in cases where a long period of time may have passed.\",\n                    \"text\": \"Example: `bot.controller.adapter.isConnected(message.user)`\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 48,\n                      \"name\": \"user\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"the id of a user, typically from `message.user`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"boolean\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"web_adapter.ts\",\n                  \"line\": 318,\n                  \"character\": 22\n                }\n              ]\n            },\n            {\n              \"id\": 38,\n              \"name\": \"processActivity\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 39,\n                  \"name\": \"processActivity\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Accept an incoming webhook request and convert it into a TurnContext which can be processed by the bot's logic.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 40,\n                      \"name\": \"req\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A request object from Restify or Express\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 41,\n                      \"name\": \"res\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A response object from Restify or Express\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 42,\n                      \"name\": \"logic\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A bot logic function in the form `async(context) => { ... }`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 43,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 44,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 45,\n                                  \"name\": \"context\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"name\": \"TurnContext\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"void\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"web_adapter.ts\",\n                              \"line\": 269,\n                              \"character\": 49\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"web_adapter.ts\",\n                  \"line\": 269,\n                  \"character\": 32\n                }\n              ]\n            },\n            {\n              \"id\": 19,\n              \"name\": \"sendActivities\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 20,\n                  \"name\": \"sendActivities\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Standard BotBuilder adapter method to send a message from the bot to the messaging API.\\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#sendactivities).\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 21,\n                      \"name\": \"context\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A TurnContext representing the current incoming message and environment. (not used)\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"TurnContext\"\n                      }\n                    },\n                    {\n                      \"id\": 22,\n                      \"name\": \"activities\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An array of outgoing activities to be sent back to the messaging API.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"reference\",\n                          \"typeArguments\": [\n                            {\n                              \"type\": \"reference\",\n                              \"name\": \"Activity\"\n                            }\n                          ],\n                          \"name\": \"Partial\"\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"reference\",\n                          \"name\": \"ResourceResponse\"\n                        }\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"web_adapter.ts\",\n                  \"line\": 193,\n                  \"character\": 31\n                }\n              ]\n            }\n          ],\n          \"constructors\": [\n            {\n              \"id\": 5,\n              \"name\": \"constructor\",\n              \"kind\": 512,\n              \"kindString\": \"Constructor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Create an adapter to handle incoming messages from a websocket and/or webhook and translate them into a standard format for processing by your bot.\",\n                \"text\": \"To use with Botkit:\\n```javascript\\nconst adapter = new WebAdapter();\\nconst controller = new Botkit({\\n     adapter: adapter,\\n     // other options\\n});\\n```\\n\\nTo use with BotBuilder:\\n```javascript\\nconst adapter = new WebAdapter();\\nconst server = restify.createServer();\\nserver.use(restify.plugins.bodyParser());\\n// instead of binding processActivity to the incoming request, pass in turn handler logic to createSocketServer\\nlet options = {}; // socket server configuration options\\nadapter.createSocketServer(server, options, async(context) => {\\n // handle turn here\\n});\\n```\\n\"\n              },\n              \"signatures\": [\n                {\n                  \"id\": 6,\n                  \"name\": \"new WebAdapter\",\n                  \"kind\": 16384,\n                  \"kindString\": \"Constructor signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Create an adapter to handle incoming messages from a websocket and/or webhook and translate them into a standard format for processing by your bot.\",\n                    \"text\": \"To use with Botkit:\\n```javascript\\nconst adapter = new WebAdapter();\\nconst controller = new Botkit({\\n     adapter: adapter,\\n     // other options\\n});\\n```\\n\\nTo use with BotBuilder:\\n```javascript\\nconst adapter = new WebAdapter();\\nconst server = restify.createServer();\\nserver.use(restify.plugins.bodyParser());\\n// instead of binding processActivity to the incoming request, pass in turn handler logic to createSocketServer\\nlet options = {}; // socket server configuration options\\nadapter.createSocketServer(server, options, async(context) => {\\n // handle turn here\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 7,\n                      \"name\": \"socketServerOptions\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"an optional object containing parameters to send to a call to [WebSocket.server](https://github.com/websockets/ws/blob/master/doc/ws.md#new-websocketserveroptions-callback).\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 8,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"indexSignature\": [\n                            {\n                              \"id\": 9,\n                              \"name\": \"__index\",\n                              \"kind\": 8192,\n                              \"kindString\": \"Index signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 10,\n                                  \"name\": \"key\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"string\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"intrinsic\",\n                                \"name\": \"any\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"web_adapter.ts\",\n                              \"line\": 64,\n                              \"character\": 44\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 2,\n                    \"name\": \"WebAdapter\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"web_adapter.ts\",\n                  \"line\": 36,\n                  \"character\": 6\n                }\n              ]\n            }\n          ]\n        }\n      ],\n      \"interfaces\": []\n    },\n    {\n      \"name\": \"Botkit for Webex Teams\",\n      \"packageName\": \"botbuilder-adapter-webex\",\n      \"path\": \"reference/webex.md\",\n      \"classes\": [\n        {\n          \"id\": 30,\n          \"name\": \"WebexAdapter\",\n          \"kind\": 128,\n          \"kindString\": \"Class\",\n          \"flags\": {\n            \"isExported\": true,\n            \"isExternal\": true\n          },\n          \"comment\": {\n            \"shortText\": \"Connect [Botkit](https://www.npmjs.com/package/botkit) or [BotBuilder](https://www.npmjs.com/package/botbuilder) to Webex Teams.\"\n          },\n          \"children\": [\n            {\n              \"id\": 34,\n              \"name\": \"constructor\",\n              \"kind\": 512,\n              \"kindString\": \"Constructor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Create a Webex adapter. See [WebexAdapterOptions](#webexadapteroptions) for a full definition of the allowed parameters.\",\n                \"text\": \"Use with Botkit:\\n```javascript\\nconst adapter = new WebexAdapter({\\n     access_token: process.env.ACCESS_TOKEN, // access token from https://developer.webex.com\\n     public_address: process.env.PUBLIC_ADDRESS,  // public url of this app https://myapp.com/\\n     secret: process.env.SECRET // webhook validation secret - you can define this yourself\\n});\\nconst controller = new Botkit({\\n     adapter: adapter,\\n     // ... other configuration options\\n});\\n```\\n\\nUse with BotBuilder:\\n```javascript\\nconst adapter = new WebexAdapter({\\n     access_token: process.env.ACCESS_TOKEN, // access token from https://developer.webex.com\\n     public_address: process.env.PUBLIC_ADDRESS,  // public url of this app https://myapp.com/\\n     secret: process.env.SECRET // webhook validation secret - you can define this yourself\\n});\\n\\n// set up restify...\\nconst server = restify.createServer();\\nserver.use(restify.plugins.bodyParser());\\n// register the webhook subscription to start receiving messages - Botkit does this automatically!\\nadapter.registerWebhookSubscription('/api/messages');\\n// Load up the bot's identity, otherwise it won't know how to filter messages from itself\\nadapter.getIdentity();\\n// create an endpoint for receiving messages\\nserver.post('/api/messages', (req, res) => {\\n     adapter.processActivity(req, res, async(context) => {\\n         // do your bot logic here!\\n     });\\n});\\n```\\n\"\n              },\n              \"signatures\": [\n                {\n                  \"id\": 35,\n                  \"name\": \"new WebexAdapter\",\n                  \"kind\": 16384,\n                  \"kindString\": \"Constructor signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Create a Webex adapter. See [WebexAdapterOptions](#webexadapteroptions) for a full definition of the allowed parameters.\",\n                    \"text\": \"Use with Botkit:\\n```javascript\\nconst adapter = new WebexAdapter({\\n     access_token: process.env.ACCESS_TOKEN, // access token from https://developer.webex.com\\n     public_address: process.env.PUBLIC_ADDRESS,  // public url of this app https://myapp.com/\\n     secret: process.env.SECRET // webhook validation secret - you can define this yourself\\n});\\nconst controller = new Botkit({\\n     adapter: adapter,\\n     // ... other configuration options\\n});\\n```\\n\\nUse with BotBuilder:\\n```javascript\\nconst adapter = new WebexAdapter({\\n     access_token: process.env.ACCESS_TOKEN, // access token from https://developer.webex.com\\n     public_address: process.env.PUBLIC_ADDRESS,  // public url of this app https://myapp.com/\\n     secret: process.env.SECRET // webhook validation secret - you can define this yourself\\n});\\n\\n// set up restify...\\nconst server = restify.createServer();\\nserver.use(restify.plugins.bodyParser());\\n// register the webhook subscription to start receiving messages - Botkit does this automatically!\\nadapter.registerWebhookSubscription('/api/messages');\\n// Load up the bot's identity, otherwise it won't know how to filter messages from itself\\nadapter.getIdentity();\\n// create an endpoint for receiving messages\\nserver.post('/api/messages', (req, res) => {\\n     adapter.processActivity(req, res, async(context) => {\\n         // do your bot logic here!\\n     });\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 36,\n                      \"name\": \"config\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 24,\n                        \"name\": \"WebexAdapterOptions\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 30,\n                    \"name\": \"WebexAdapter\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"webex_adapter.ts\",\n                  \"line\": 67,\n                  \"character\": 42\n                }\n              ]\n            },\n            {\n              \"id\": 39,\n              \"name\": \"identity\",\n              \"kind\": 262144,\n              \"kindString\": \"Accessor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Returns the identity of the bot, including {id, emails, displayName, created} and anything else from [this spec](https://webex.github.io/spark-js-sdk/api/#personobject)\"\n              },\n              \"getSignature\": [\n                {\n                  \"id\": 40,\n                  \"name\": \"__get\",\n                  \"kind\": 524288,\n                  \"kindString\": \"Get signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Returns the identity of the bot, including {id, emails, displayName, created} and anything else from [this spec](https://webex.github.io/spark-js-sdk/api/#personobject)\"\n                  },\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"any\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"webex_adapter.ts\",\n                  \"line\": 212,\n                  \"character\": 23\n                }\n              ]\n            },\n            {\n              \"id\": 64,\n              \"name\": \"continueConversation\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 65,\n                  \"name\": \"continueConversation\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Standard BotBuilder adapter method for continuing an existing conversation based on a conversation reference.\\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#continueconversation)\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 66,\n                      \"name\": \"reference\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A conversation reference to be applied to future messages.\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"ConversationReference\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    },\n                    {\n                      \"id\": 67,\n                      \"name\": \"logic\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A bot logic function that will perform continuing action in the form `async(context) => { ... }`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 68,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 69,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 70,\n                                  \"name\": \"context\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"name\": \"TurnContext\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"void\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"webex_adapter.ts\",\n                              \"line\": 450,\n                              \"character\": 87\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"webex_adapter.ts\",\n                  \"line\": 450,\n                  \"character\": 37\n                }\n              ]\n            },\n            {\n              \"id\": 60,\n              \"name\": \"deleteActivity\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 61,\n                  \"name\": \"deleteActivity\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Standard BotBuilder adapter method to delete a previous message.\\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#deleteactivity).\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 62,\n                      \"name\": \"context\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A TurnContext representing the current incoming message and environment. (not used)\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"TurnContext\"\n                      }\n                    },\n                    {\n                      \"id\": 63,\n                      \"name\": \"reference\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An object in the form `{activityId: <id of message to delete>, conversation: { id: <id of slack channel>}}`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"ConversationReference\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"webex_adapter.ts\",\n                  \"line\": 432,\n                  \"character\": 31\n                }\n              ]\n            },\n            {\n              \"id\": 37,\n              \"name\": \"getIdentity\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 38,\n                  \"name\": \"getIdentity\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Load the bot's identity via the Webex API.\\nMUST be called by BotBuilder bots in order to filter messages sent by the bot.\"\n                  },\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"webex_adapter.ts\",\n                  \"line\": 193,\n                  \"character\": 28\n                }\n              ]\n            },\n            {\n              \"id\": 41,\n              \"name\": \"init\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 42,\n                  \"name\": \"init\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Botkit-only: Initialization function called automatically when used with Botkit.\\n     * Calls registerWebhookSubscription() during bootup.\\n     * Calls getIdentit() to load the bot's identity.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 43,\n                      \"name\": \"botkit\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"webex_adapter.ts\",\n                  \"line\": 221,\n                  \"character\": 15\n                }\n              ]\n            },\n            {\n              \"id\": 71,\n              \"name\": \"processActivity\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 72,\n                  \"name\": \"processActivity\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Accept an incoming webhook request and convert it into a TurnContext which can be processed by the bot's logic.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 73,\n                      \"name\": \"req\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A request object from Restify or Express\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 74,\n                      \"name\": \"res\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A response object from Restify or Express\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 75,\n                      \"name\": \"logic\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A bot logic function in the form `async(context) => { ... }`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 76,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 77,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 78,\n                                  \"name\": \"context\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"name\": \"TurnContext\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"void\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"webex_adapter.ts\",\n                              \"line\": 467,\n                              \"character\": 49\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"webex_adapter.ts\",\n                  \"line\": 467,\n                  \"character\": 32\n                }\n              ]\n            },\n            {\n              \"id\": 49,\n              \"name\": \"registerAdaptiveCardWebhookSubscription\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 50,\n                  \"name\": \"registerAdaptiveCardWebhookSubscription\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Register a webhook subscription with Webex Teams to start receiving message events.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 51,\n                      \"name\": \"webhook_path\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"the path of the webhook endpoint like `/api/messages`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"webex_adapter.ts\",\n                  \"line\": 309,\n                  \"character\": 50\n                }\n              ]\n            },\n            {\n              \"id\": 46,\n              \"name\": \"registerWebhookSubscription\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 47,\n                  \"name\": \"registerWebhookSubscription\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Register a webhook subscription with Webex Teams to start receiving message events.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 48,\n                      \"name\": \"webhook_path\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"the path of the webhook endpoint like `/api/messages`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"webex_adapter.ts\",\n                  \"line\": 256,\n                  \"character\": 38\n                }\n              ]\n            },\n            {\n              \"id\": 44,\n              \"name\": \"resetWebhookSubscriptions\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 45,\n                  \"name\": \"resetWebhookSubscriptions\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Clear out and reset all the webhook subscriptions currently associated with this application.\"\n                  },\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"webex_adapter.ts\",\n                  \"line\": 241,\n                  \"character\": 42\n                }\n              ]\n            },\n            {\n              \"id\": 52,\n              \"name\": \"sendActivities\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 53,\n                  \"name\": \"sendActivities\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Standard BotBuilder adapter method to send a message from the bot to the messaging API.\\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#sendactivities).\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 54,\n                      \"name\": \"context\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A TurnContext representing the current incoming message and environment.\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"TurnContext\"\n                      }\n                    },\n                    {\n                      \"id\": 55,\n                      \"name\": \"activities\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An array of outgoing activities to be sent back to the messaging API.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"reference\",\n                          \"typeArguments\": [\n                            {\n                              \"type\": \"reference\",\n                              \"name\": \"Activity\"\n                            }\n                          ],\n                          \"name\": \"Partial\"\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"reference\",\n                          \"name\": \"ResourceResponse\"\n                        }\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"webex_adapter.ts\",\n                  \"line\": 364,\n                  \"character\": 31\n                }\n              ]\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Constructors\",\n              \"kind\": 512,\n              \"children\": [\n                34\n              ]\n            },\n            {\n              \"title\": \"Accessors\",\n              \"kind\": 262144,\n              \"children\": [\n                39\n              ]\n            },\n            {\n              \"title\": \"Methods\",\n              \"kind\": 2048,\n              \"children\": [\n                64,\n                60,\n                37,\n                41,\n                71,\n                49,\n                46,\n                44,\n                52\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"webex_adapter.ts\",\n              \"line\": 45,\n              \"character\": 25\n            }\n          ],\n          \"extendedTypes\": [\n            {\n              \"type\": \"intrinsic\",\n              \"name\": \"any\"\n            }\n          ],\n          \"props\": [\n            {\n              \"id\": 39,\n              \"name\": \"identity\",\n              \"kind\": 262144,\n              \"kindString\": \"Accessor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Returns the identity of the bot, including {id, emails, displayName, created} and anything else from [this spec](https://webex.github.io/spark-js-sdk/api/#personobject)\"\n              },\n              \"getSignature\": [\n                {\n                  \"id\": 40,\n                  \"name\": \"__get\",\n                  \"kind\": 524288,\n                  \"kindString\": \"Get signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Returns the identity of the bot, including {id, emails, displayName, created} and anything else from [this spec](https://webex.github.io/spark-js-sdk/api/#personobject)\"\n                  },\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"any\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"webex_adapter.ts\",\n                  \"line\": 212,\n                  \"character\": 23\n                }\n              ]\n            }\n          ],\n          \"methods\": [\n            {\n              \"id\": 64,\n              \"name\": \"continueConversation\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 65,\n                  \"name\": \"continueConversation\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Standard BotBuilder adapter method for continuing an existing conversation based on a conversation reference.\\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#continueconversation)\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 66,\n                      \"name\": \"reference\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A conversation reference to be applied to future messages.\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"ConversationReference\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    },\n                    {\n                      \"id\": 67,\n                      \"name\": \"logic\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A bot logic function that will perform continuing action in the form `async(context) => { ... }`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 68,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 69,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 70,\n                                  \"name\": \"context\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"name\": \"TurnContext\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"void\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"webex_adapter.ts\",\n                              \"line\": 450,\n                              \"character\": 87\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"webex_adapter.ts\",\n                  \"line\": 450,\n                  \"character\": 37\n                }\n              ]\n            },\n            {\n              \"id\": 60,\n              \"name\": \"deleteActivity\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 61,\n                  \"name\": \"deleteActivity\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Standard BotBuilder adapter method to delete a previous message.\\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#deleteactivity).\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 62,\n                      \"name\": \"context\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A TurnContext representing the current incoming message and environment. (not used)\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"TurnContext\"\n                      }\n                    },\n                    {\n                      \"id\": 63,\n                      \"name\": \"reference\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An object in the form `{activityId: <id of message to delete>, conversation: { id: <id of slack channel>}}`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"ConversationReference\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"webex_adapter.ts\",\n                  \"line\": 432,\n                  \"character\": 31\n                }\n              ]\n            },\n            {\n              \"id\": 37,\n              \"name\": \"getIdentity\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 38,\n                  \"name\": \"getIdentity\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Load the bot's identity via the Webex API.\\nMUST be called by BotBuilder bots in order to filter messages sent by the bot.\"\n                  },\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"webex_adapter.ts\",\n                  \"line\": 193,\n                  \"character\": 28\n                }\n              ]\n            },\n            {\n              \"id\": 41,\n              \"name\": \"init\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 42,\n                  \"name\": \"init\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Botkit-only: Initialization function called automatically when used with Botkit.\\n     * Calls registerWebhookSubscription() during bootup.\\n     * Calls getIdentit() to load the bot's identity.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 43,\n                      \"name\": \"botkit\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"webex_adapter.ts\",\n                  \"line\": 221,\n                  \"character\": 15\n                }\n              ]\n            },\n            {\n              \"id\": 71,\n              \"name\": \"processActivity\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 72,\n                  \"name\": \"processActivity\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Accept an incoming webhook request and convert it into a TurnContext which can be processed by the bot's logic.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 73,\n                      \"name\": \"req\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A request object from Restify or Express\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 74,\n                      \"name\": \"res\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A response object from Restify or Express\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 75,\n                      \"name\": \"logic\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A bot logic function in the form `async(context) => { ... }`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 76,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 77,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 78,\n                                  \"name\": \"context\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"name\": \"TurnContext\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"void\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"webex_adapter.ts\",\n                              \"line\": 467,\n                              \"character\": 49\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"webex_adapter.ts\",\n                  \"line\": 467,\n                  \"character\": 32\n                }\n              ]\n            },\n            {\n              \"id\": 49,\n              \"name\": \"registerAdaptiveCardWebhookSubscription\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 50,\n                  \"name\": \"registerAdaptiveCardWebhookSubscription\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Register a webhook subscription with Webex Teams to start receiving message events.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 51,\n                      \"name\": \"webhook_path\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"the path of the webhook endpoint like `/api/messages`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"webex_adapter.ts\",\n                  \"line\": 309,\n                  \"character\": 50\n                }\n              ]\n            },\n            {\n              \"id\": 46,\n              \"name\": \"registerWebhookSubscription\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 47,\n                  \"name\": \"registerWebhookSubscription\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Register a webhook subscription with Webex Teams to start receiving message events.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 48,\n                      \"name\": \"webhook_path\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"the path of the webhook endpoint like `/api/messages`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"webex_adapter.ts\",\n                  \"line\": 256,\n                  \"character\": 38\n                }\n              ]\n            },\n            {\n              \"id\": 44,\n              \"name\": \"resetWebhookSubscriptions\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 45,\n                  \"name\": \"resetWebhookSubscriptions\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Clear out and reset all the webhook subscriptions currently associated with this application.\"\n                  },\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"webex_adapter.ts\",\n                  \"line\": 241,\n                  \"character\": 42\n                }\n              ]\n            },\n            {\n              \"id\": 52,\n              \"name\": \"sendActivities\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 53,\n                  \"name\": \"sendActivities\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Standard BotBuilder adapter method to send a message from the bot to the messaging API.\\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#sendactivities).\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 54,\n                      \"name\": \"context\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A TurnContext representing the current incoming message and environment.\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"TurnContext\"\n                      }\n                    },\n                    {\n                      \"id\": 55,\n                      \"name\": \"activities\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An array of outgoing activities to be sent back to the messaging API.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"reference\",\n                          \"typeArguments\": [\n                            {\n                              \"type\": \"reference\",\n                              \"name\": \"Activity\"\n                            }\n                          ],\n                          \"name\": \"Partial\"\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"reference\",\n                          \"name\": \"ResourceResponse\"\n                        }\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"webex_adapter.ts\",\n                  \"line\": 364,\n                  \"character\": 31\n                }\n              ]\n            }\n          ],\n          \"constructors\": [\n            {\n              \"id\": 34,\n              \"name\": \"constructor\",\n              \"kind\": 512,\n              \"kindString\": \"Constructor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Create a Webex adapter. See [WebexAdapterOptions](#webexadapteroptions) for a full definition of the allowed parameters.\",\n                \"text\": \"Use with Botkit:\\n```javascript\\nconst adapter = new WebexAdapter({\\n     access_token: process.env.ACCESS_TOKEN, // access token from https://developer.webex.com\\n     public_address: process.env.PUBLIC_ADDRESS,  // public url of this app https://myapp.com/\\n     secret: process.env.SECRET // webhook validation secret - you can define this yourself\\n});\\nconst controller = new Botkit({\\n     adapter: adapter,\\n     // ... other configuration options\\n});\\n```\\n\\nUse with BotBuilder:\\n```javascript\\nconst adapter = new WebexAdapter({\\n     access_token: process.env.ACCESS_TOKEN, // access token from https://developer.webex.com\\n     public_address: process.env.PUBLIC_ADDRESS,  // public url of this app https://myapp.com/\\n     secret: process.env.SECRET // webhook validation secret - you can define this yourself\\n});\\n\\n// set up restify...\\nconst server = restify.createServer();\\nserver.use(restify.plugins.bodyParser());\\n// register the webhook subscription to start receiving messages - Botkit does this automatically!\\nadapter.registerWebhookSubscription('/api/messages');\\n// Load up the bot's identity, otherwise it won't know how to filter messages from itself\\nadapter.getIdentity();\\n// create an endpoint for receiving messages\\nserver.post('/api/messages', (req, res) => {\\n     adapter.processActivity(req, res, async(context) => {\\n         // do your bot logic here!\\n     });\\n});\\n```\\n\"\n              },\n              \"signatures\": [\n                {\n                  \"id\": 35,\n                  \"name\": \"new WebexAdapter\",\n                  \"kind\": 16384,\n                  \"kindString\": \"Constructor signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Create a Webex adapter. See [WebexAdapterOptions](#webexadapteroptions) for a full definition of the allowed parameters.\",\n                    \"text\": \"Use with Botkit:\\n```javascript\\nconst adapter = new WebexAdapter({\\n     access_token: process.env.ACCESS_TOKEN, // access token from https://developer.webex.com\\n     public_address: process.env.PUBLIC_ADDRESS,  // public url of this app https://myapp.com/\\n     secret: process.env.SECRET // webhook validation secret - you can define this yourself\\n});\\nconst controller = new Botkit({\\n     adapter: adapter,\\n     // ... other configuration options\\n});\\n```\\n\\nUse with BotBuilder:\\n```javascript\\nconst adapter = new WebexAdapter({\\n     access_token: process.env.ACCESS_TOKEN, // access token from https://developer.webex.com\\n     public_address: process.env.PUBLIC_ADDRESS,  // public url of this app https://myapp.com/\\n     secret: process.env.SECRET // webhook validation secret - you can define this yourself\\n});\\n\\n// set up restify...\\nconst server = restify.createServer();\\nserver.use(restify.plugins.bodyParser());\\n// register the webhook subscription to start receiving messages - Botkit does this automatically!\\nadapter.registerWebhookSubscription('/api/messages');\\n// Load up the bot's identity, otherwise it won't know how to filter messages from itself\\nadapter.getIdentity();\\n// create an endpoint for receiving messages\\nserver.post('/api/messages', (req, res) => {\\n     adapter.processActivity(req, res, async(context) => {\\n         // do your bot logic here!\\n     });\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 36,\n                      \"name\": \"config\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 24,\n                        \"name\": \"WebexAdapterOptions\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 30,\n                    \"name\": \"WebexAdapter\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"webex_adapter.ts\",\n                  \"line\": 67,\n                  \"character\": 42\n                }\n              ]\n            }\n          ]\n        },\n        {\n          \"id\": 2,\n          \"name\": \"WebexBotWorker\",\n          \"kind\": 128,\n          \"kindString\": \"Class\",\n          \"flags\": {\n            \"isExported\": true,\n            \"isExternal\": true\n          },\n          \"comment\": {\n            \"shortText\": \"This is a specialized version of [Botkit's core BotWorker class](core.md#BotWorker) that includes additional methods for interacting with Webex Teams.\\nIt includes all functionality from the base class, as well as the extension methods below.\",\n            \"text\": \"When using the WebexAdapter with Botkit, all `bot` objects passed to handler functions will include these extensions.\\n\"\n          },\n          \"children\": [\n            {\n              \"id\": 3,\n              \"name\": \"api\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"An instance of the [webex api client](https://www.npmjs.com/package/webex)\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 22,\n                  \"character\": 14\n                }\n              ],\n              \"type\": {\n                \"type\": \"reference\",\n                \"name\": \"Webex\"\n              }\n            },\n            {\n              \"id\": 20,\n              \"name\": \"deleteMessage\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 21,\n                  \"name\": \"deleteMessage\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Delete an existing message.\",\n                    \"text\": \"```javascript\\n// send a reply, capture the results\\nlet sent = await bot.reply(message,'this is my original reply...');\\n\\n// delete the sent message using the sent.id field\\nawait bot.deleteMessage(sent);\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 22,\n                      \"name\": \"update\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An object in the form of `{id: <id of message to delete>}`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"BotkitMessage\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 157,\n                  \"character\": 30\n                }\n              ]\n            },\n            {\n              \"id\": 16,\n              \"name\": \"replyInThread\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 17,\n                  \"name\": \"replyInThread\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Like bot.reply, but as a threaded response to the incoming message rather than a new message in the main channel.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 18,\n                      \"name\": \"src\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"an incoming message object\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 19,\n                      \"name\": \"resp\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"an outgoing message object (or part of one or just reply text)\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 138,\n                  \"character\": 30\n                }\n              ]\n            },\n            {\n              \"id\": 7,\n              \"name\": \"startConversationInRoom\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 8,\n                  \"name\": \"startConversationInRoom\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Switch a bot's context into a different room.\\nAfter calling this method, messages sent with `bot.say` and any dialogs started with `bot.beginDialog` will occur in this new context.\",\n                    \"text\": \"```javascript\\ncontroller.hears('take this offline', 'message', async(bot, message) => {\\n\\n     // switch to a different channel\\n     await bot.startConversationInRoom(WEBEX_ROOM_ID, message.user);\\n\\n     // say hello\\n     await bot.say('Shall we discuss this matter over here?');\\n     // ... continue...\\n     await bot.beginDialog(ANOTHER_DIALOG);\\n\\n});\\n```\\n\\nAlso useful when sending pro-active messages such as those sent on a schedule or in response to external events:\\n```javascript\\n// Spawn a worker\\nlet bot = await controller.spawn();\\n\\n// Set the context for the bot's next action...\\nawait bot.startConversationInRoom(CACHED_ROOM_ID, CACHED_USER_ID);\\n\\n// Begin a dialog in the 1:1 context\\nawait bot.beginDialog(ALERT_DIALOG);\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 9,\n                      \"name\": \"roomId\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A Webex rooom id, like one found in `message.channel`\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 10,\n                      \"name\": \"userId\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A Webex user id, like one found in `message.user`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 75,\n                  \"character\": 40\n                }\n              ]\n            },\n            {\n              \"id\": 11,\n              \"name\": \"startConversationInThread\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 12,\n                  \"name\": \"startConversationInThread\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Switch a bot's context into a specific thread within a room.\\nAfter calling this method, messages sent with `bot.say` and any dialogs started with `bot.beginDialog` will occur in this new context.\",\n                    \"text\": \"```javascript\\ncontroller.hears('take this offline', 'message', async(bot, message) => {\\n\\n     // switch to a different channel\\n     await bot.startConversationInThread(WEBEX_ROOM_ID, message.user, message.id);\\n\\n     // say hello\\n     await bot.say('Shall we discuss this matter over here?');\\n     // ... continue...\\n     await bot.beginDialog(ANOTHER_DIALOG);\\n\\n});\\n```\\n\\nAlso useful when sending pro-active messages such as those sent on a schedule or in response to external events:\\n```javascript\\n// Spawn a worker\\nlet bot = await controller.spawn();\\n\\n// Set the context for the bot's next action...\\nawait bot.startConversationInRoom(CACHED_ROOM_ID, CACHED_USER_ID);\\n\\n// Begin a dialog in the 1:1 context\\nawait bot.beginDialog(ALERT_DIALOG);\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 13,\n                      \"name\": \"roomId\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A Webex rooom id, like one found in `message.channel`\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 14,\n                      \"name\": \"userId\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A Webex user id, like one found in `message.user`\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 15,\n                      \"name\": \"parentId\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A webex message id that should be the parent message, like the one found in `message.id`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 120,\n                  \"character\": 42\n                }\n              ]\n            },\n            {\n              \"id\": 4,\n              \"name\": \"startPrivateConversation\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 5,\n                  \"name\": \"startPrivateConversation\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Change the context of the _next_ message\\nDue to a quirk in the Webex API, we can't know the address of the DM until after sending the first message.\\nAs a result, the internal tracking for this conversation can't be persisted properly.\\nUSE WITH CAUTION while we try to sort this out.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 6,\n                      \"name\": \"userId\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"user id of a webex teams user, like one from `message.user`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 31,\n                  \"character\": 41\n                }\n              ]\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Properties\",\n              \"kind\": 1024,\n              \"children\": [\n                3\n              ]\n            },\n            {\n              \"title\": \"Methods\",\n              \"kind\": 2048,\n              \"children\": [\n                20,\n                16,\n                7,\n                11,\n                4\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"botworker.ts\",\n              \"line\": 18,\n              \"character\": 27\n            }\n          ],\n          \"extendedTypes\": [\n            {\n              \"type\": \"intrinsic\",\n              \"name\": \"any\"\n            }\n          ],\n          \"props\": [\n            {\n              \"id\": 3,\n              \"name\": \"api\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"An instance of the [webex api client](https://www.npmjs.com/package/webex)\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 22,\n                  \"character\": 14\n                }\n              ],\n              \"type\": {\n                \"type\": \"reference\",\n                \"name\": \"Webex\"\n              }\n            }\n          ],\n          \"methods\": [\n            {\n              \"id\": 20,\n              \"name\": \"deleteMessage\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 21,\n                  \"name\": \"deleteMessage\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Delete an existing message.\",\n                    \"text\": \"```javascript\\n// send a reply, capture the results\\nlet sent = await bot.reply(message,'this is my original reply...');\\n\\n// delete the sent message using the sent.id field\\nawait bot.deleteMessage(sent);\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 22,\n                      \"name\": \"update\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An object in the form of `{id: <id of message to delete>}`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"BotkitMessage\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 157,\n                  \"character\": 30\n                }\n              ]\n            },\n            {\n              \"id\": 16,\n              \"name\": \"replyInThread\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 17,\n                  \"name\": \"replyInThread\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Like bot.reply, but as a threaded response to the incoming message rather than a new message in the main channel.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 18,\n                      \"name\": \"src\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"an incoming message object\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 19,\n                      \"name\": \"resp\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"an outgoing message object (or part of one or just reply text)\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 138,\n                  \"character\": 30\n                }\n              ]\n            },\n            {\n              \"id\": 7,\n              \"name\": \"startConversationInRoom\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 8,\n                  \"name\": \"startConversationInRoom\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Switch a bot's context into a different room.\\nAfter calling this method, messages sent with `bot.say` and any dialogs started with `bot.beginDialog` will occur in this new context.\",\n                    \"text\": \"```javascript\\ncontroller.hears('take this offline', 'message', async(bot, message) => {\\n\\n     // switch to a different channel\\n     await bot.startConversationInRoom(WEBEX_ROOM_ID, message.user);\\n\\n     // say hello\\n     await bot.say('Shall we discuss this matter over here?');\\n     // ... continue...\\n     await bot.beginDialog(ANOTHER_DIALOG);\\n\\n});\\n```\\n\\nAlso useful when sending pro-active messages such as those sent on a schedule or in response to external events:\\n```javascript\\n// Spawn a worker\\nlet bot = await controller.spawn();\\n\\n// Set the context for the bot's next action...\\nawait bot.startConversationInRoom(CACHED_ROOM_ID, CACHED_USER_ID);\\n\\n// Begin a dialog in the 1:1 context\\nawait bot.beginDialog(ALERT_DIALOG);\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 9,\n                      \"name\": \"roomId\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A Webex rooom id, like one found in `message.channel`\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 10,\n                      \"name\": \"userId\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A Webex user id, like one found in `message.user`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 75,\n                  \"character\": 40\n                }\n              ]\n            },\n            {\n              \"id\": 11,\n              \"name\": \"startConversationInThread\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 12,\n                  \"name\": \"startConversationInThread\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Switch a bot's context into a specific thread within a room.\\nAfter calling this method, messages sent with `bot.say` and any dialogs started with `bot.beginDialog` will occur in this new context.\",\n                    \"text\": \"```javascript\\ncontroller.hears('take this offline', 'message', async(bot, message) => {\\n\\n     // switch to a different channel\\n     await bot.startConversationInThread(WEBEX_ROOM_ID, message.user, message.id);\\n\\n     // say hello\\n     await bot.say('Shall we discuss this matter over here?');\\n     // ... continue...\\n     await bot.beginDialog(ANOTHER_DIALOG);\\n\\n});\\n```\\n\\nAlso useful when sending pro-active messages such as those sent on a schedule or in response to external events:\\n```javascript\\n// Spawn a worker\\nlet bot = await controller.spawn();\\n\\n// Set the context for the bot's next action...\\nawait bot.startConversationInRoom(CACHED_ROOM_ID, CACHED_USER_ID);\\n\\n// Begin a dialog in the 1:1 context\\nawait bot.beginDialog(ALERT_DIALOG);\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 13,\n                      \"name\": \"roomId\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A Webex rooom id, like one found in `message.channel`\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 14,\n                      \"name\": \"userId\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A Webex user id, like one found in `message.user`\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 15,\n                      \"name\": \"parentId\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A webex message id that should be the parent message, like the one found in `message.id`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 120,\n                  \"character\": 42\n                }\n              ]\n            },\n            {\n              \"id\": 4,\n              \"name\": \"startPrivateConversation\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 5,\n                  \"name\": \"startPrivateConversation\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Change the context of the _next_ message\\nDue to a quirk in the Webex API, we can't know the address of the DM until after sending the first message.\\nAs a result, the internal tracking for this conversation can't be persisted properly.\\nUSE WITH CAUTION while we try to sort this out.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 6,\n                      \"name\": \"userId\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"user id of a webex teams user, like one from `message.user`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 31,\n                  \"character\": 41\n                }\n              ]\n            }\n          ],\n          \"constructors\": []\n        }\n      ],\n      \"interfaces\": [\n        {\n          \"id\": 24,\n          \"name\": \"WebexAdapterOptions\",\n          \"kind\": 256,\n          \"kindString\": \"Interface\",\n          \"flags\": {\n            \"isExported\": true,\n            \"isExternal\": true\n          },\n          \"children\": [\n            {\n              \"id\": 25,\n              \"name\": \"access_token\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"An access token for the bot. Get one from [https://developer.webex.com/](https://developer.webex.com/)\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"webex_adapter.ts\",\n                  \"line\": 21,\n                  \"character\": 16\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 29,\n              \"name\": \"enable_incomplete\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Allow the adapter to startup without a complete configuration.\\nThis is risky as it may result in a non-functioning or insecure adapter.\\nThis should only be used when getting started.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"webex_adapter.ts\",\n                  \"line\": 39,\n                  \"character\": 21\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"boolean\"\n              }\n            },\n            {\n              \"id\": 27,\n              \"name\": \"public_address\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"The root URL of your bot application.  Something like `https://mybot.com/`\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"webex_adapter.ts\",\n                  \"line\": 29,\n                  \"character\": 18\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 26,\n              \"name\": \"secret\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Secret used to validate incoming webhooks - you can define this yourself\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"webex_adapter.ts\",\n                  \"line\": 25,\n                  \"character\": 10\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 28,\n              \"name\": \"webhook_name\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"a name for the webhook subscription that will be created to tell Webex to send your bot webhooks.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"webex_adapter.ts\",\n                  \"line\": 33,\n                  \"character\": 16\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Properties\",\n              \"kind\": 1024,\n              \"children\": [\n                25,\n                29,\n                27,\n                26,\n                28\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"webex_adapter.ts\",\n              \"line\": 17,\n              \"character\": 36\n            }\n          ],\n          \"props\": [\n            {\n              \"id\": 25,\n              \"name\": \"access_token\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"An access token for the bot. Get one from [https://developer.webex.com/](https://developer.webex.com/)\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"webex_adapter.ts\",\n                  \"line\": 21,\n                  \"character\": 16\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 29,\n              \"name\": \"enable_incomplete\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Allow the adapter to startup without a complete configuration.\\nThis is risky as it may result in a non-functioning or insecure adapter.\\nThis should only be used when getting started.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"webex_adapter.ts\",\n                  \"line\": 39,\n                  \"character\": 21\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"boolean\"\n              }\n            },\n            {\n              \"id\": 27,\n              \"name\": \"public_address\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"The root URL of your bot application.  Something like `https://mybot.com/`\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"webex_adapter.ts\",\n                  \"line\": 29,\n                  \"character\": 18\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 26,\n              \"name\": \"secret\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Secret used to validate incoming webhooks - you can define this yourself\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"webex_adapter.ts\",\n                  \"line\": 25,\n                  \"character\": 10\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 28,\n              \"name\": \"webhook_name\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"a name for the webhook subscription that will be created to tell Webex to send your bot webhooks.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"webex_adapter.ts\",\n                  \"line\": 33,\n                  \"character\": 16\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            }\n          ]\n        }\n      ]\n    },\n    {\n      \"name\": \"Botkit for Slack\",\n      \"packageName\": \"botbuilder-adapter-slack\",\n      \"path\": \"reference/slack.md\",\n      \"classes\": [\n        {\n          \"id\": 60,\n          \"name\": \"SlackAdapter\",\n          \"kind\": 128,\n          \"kindString\": \"Class\",\n          \"flags\": {\n            \"isExported\": true,\n            \"isExternal\": true\n          },\n          \"comment\": {\n            \"shortText\": \"Connect [Botkit](https://www.npmjs.com/package/botkit) or [BotBuilder](https://www.npmjs.com/package/botbuilder) to Slack.\"\n          },\n          \"children\": [\n            {\n              \"id\": 64,\n              \"name\": \"constructor\",\n              \"kind\": 512,\n              \"kindString\": \"Constructor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Create a Slack adapter.\",\n                \"text\": \"The SlackAdapter can be used in 2 modes:\\n     * As an \\\"[internal integration](https://api.slack.com/internal-integrations) connected to a single Slack workspace\\n     * As a \\\"[Slack app](https://api.slack.com/slack-apps) that uses oauth to connect to multiple workspaces and can be submitted to the Slack app.\\n\\n[Read here for more information about all the ways to configure the SlackAdapter &rarr;](../../botbuilder-adapter-slack/readme.md).\\n\\nUse with Botkit:\\n```javascript\\nconst adapter = new SlackAdapter({\\n     clientSigningSecret: process.env.CLIENT_SIGNING_SECRET,\\n     botToken: process.env.BOT_TOKEN\\n});\\nconst controller = new Botkit({\\n     adapter: adapter,\\n     // ... other configuration options\\n});\\n```\\n\\nUse with BotBuilder:\\n```javascript\\nconst adapter = new SlackAdapter({\\n     clientSigningSecret: process.env.CLIENT_SIGNING_SECRET,\\n     botToken: process.env.BOT_TOKEN\\n});\\n// set up restify...\\nconst server = restify.createServer();\\nserver.use(restify.plugins.bodyParser());\\nserver.post('/api/messages', (req, res) => {\\n     adapter.processActivity(req, res, async(context) => {\\n         // do your bot logic here!\\n     });\\n});\\n```\\n\\nUse in \\\"Slack app\\\" multi-team mode:\\n```javascript\\nconst adapter = new SlackAdapter({\\n    clientSigningSecret: process.env.CLIENT_SIGNING_SECRET,\\n    clientId: process.env.CLIENT_ID, // oauth client id\\n    clientSecret: process.env.CLIENT_SECRET, // oauth client secret\\n    scopes: ['bot'], // oauth scopes requested\\n    oauthVersion: 'v1',\\n    redirectUri: process.env.REDIRECT_URI, // url to redirect post login defaults to `https://<mydomain>/install/auth`\\n    getTokenForTeam: async(team_id) => Promise<string>, // function that returns a token based on team id\\n    getBotUserByTeam: async(team_id) => Promise<string>, // function that returns a bot's user id based on team id\\n});\\n```\\n\"\n              },\n              \"signatures\": [\n                {\n                  \"id\": 65,\n                  \"name\": \"new SlackAdapter\",\n                  \"kind\": 16384,\n                  \"kindString\": \"Constructor signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Create a Slack adapter.\",\n                    \"text\": \"The SlackAdapter can be used in 2 modes:\\n     * As an \\\"[internal integration](https://api.slack.com/internal-integrations) connected to a single Slack workspace\\n     * As a \\\"[Slack app](https://api.slack.com/slack-apps) that uses oauth to connect to multiple workspaces and can be submitted to the Slack app.\\n\\n[Read here for more information about all the ways to configure the SlackAdapter &rarr;](../../botbuilder-adapter-slack/readme.md).\\n\\nUse with Botkit:\\n```javascript\\nconst adapter = new SlackAdapter({\\n     clientSigningSecret: process.env.CLIENT_SIGNING_SECRET,\\n     botToken: process.env.BOT_TOKEN\\n});\\nconst controller = new Botkit({\\n     adapter: adapter,\\n     // ... other configuration options\\n});\\n```\\n\\nUse with BotBuilder:\\n```javascript\\nconst adapter = new SlackAdapter({\\n     clientSigningSecret: process.env.CLIENT_SIGNING_SECRET,\\n     botToken: process.env.BOT_TOKEN\\n});\\n// set up restify...\\nconst server = restify.createServer();\\nserver.use(restify.plugins.bodyParser());\\nserver.post('/api/messages', (req, res) => {\\n     adapter.processActivity(req, res, async(context) => {\\n         // do your bot logic here!\\n     });\\n});\\n```\\n\\nUse in \\\"Slack app\\\" multi-team mode:\\n```javascript\\nconst adapter = new SlackAdapter({\\n    clientSigningSecret: process.env.CLIENT_SIGNING_SECRET,\\n    clientId: process.env.CLIENT_ID, // oauth client id\\n    clientSecret: process.env.CLIENT_SECRET, // oauth client secret\\n    scopes: ['bot'], // oauth scopes requested\\n    oauthVersion: 'v1',\\n    redirectUri: process.env.REDIRECT_URI, // url to redirect post login defaults to `https://<mydomain>/install/auth`\\n    getTokenForTeam: async(team_id) => Promise<string>, // function that returns a token based on team id\\n    getBotUserByTeam: async(team_id) => Promise<string>, // function that returns a bot's user id based on team id\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 66,\n                      \"name\": \"options\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"An object containing API credentials, a webhook verification token and other options\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 108,\n                        \"name\": \"SlackAdapterOptions\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 60,\n                    \"name\": \"SlackAdapter\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 42,\n                  \"character\": 42\n                }\n              ]\n            },\n            {\n              \"id\": 78,\n              \"name\": \"activityToSlack\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 79,\n                  \"name\": \"activityToSlack\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Formats a BotBuilder activity into an outgoing Slack message.\",\n                    \"returns\": \"a Slack message object with {text, attachments, channel, thread_ts} as well as any fields found in activity.channelData\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 80,\n                      \"name\": \"activity\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A BotBuilder Activity object\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"Activity\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"any\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 317,\n                  \"character\": 26\n                }\n              ]\n            },\n            {\n              \"id\": 93,\n              \"name\": \"continueConversation\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 94,\n                  \"name\": \"continueConversation\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Standard BotBuilder adapter method for continuing an existing conversation based on a conversation reference.\\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#continueconversation)\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 95,\n                      \"name\": \"reference\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A conversation reference to be applied to future messages.\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"ConversationReference\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    },\n                    {\n                      \"id\": 96,\n                      \"name\": \"logic\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A bot logic function that will perform continuing action in the form `async(context) => { ... }`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 97,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 98,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 99,\n                                  \"name\": \"context\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"name\": \"TurnContext\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"void\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"slack_adapter.ts\",\n                              \"line\": 452,\n                              \"character\": 87\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 452,\n                  \"character\": 37\n                }\n              ]\n            },\n            {\n              \"id\": 89,\n              \"name\": \"deleteActivity\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 90,\n                  \"name\": \"deleteActivity\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Standard BotBuilder adapter method to delete a previous message.\\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#deleteactivity).\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 91,\n                      \"name\": \"context\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A TurnContext representing the current incoming message and environment.\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"TurnContext\"\n                      }\n                    },\n                    {\n                      \"id\": 92,\n                      \"name\": \"reference\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An object in the form `{activityId: <id of message to delete>, conversation: { id: <id of slack channel>}}`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"ConversationReference\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 429,\n                  \"character\": 31\n                }\n              ]\n            },\n            {\n              \"id\": 67,\n              \"name\": \"getAPI\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 68,\n                  \"name\": \"getAPI\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Get a Slack API client with the correct credentials based on the team identified in the incoming activity.\\nThis is used by many internal functions to get access to the Slack API, and is exposed as `bot.api` on any bot worker instances.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 69,\n                      \"name\": \"activity\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An incoming message activity\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"Activity\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"reference\",\n                        \"name\": \"WebClient\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 193,\n                  \"character\": 23\n                }\n              ]\n            },\n            {\n              \"id\": 70,\n              \"name\": \"getBotUserByTeam\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 71,\n                  \"name\": \"getBotUserByTeam\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Get the bot user id associated with the team on which an incoming activity originated. This is used internally by the SlackMessageTypeMiddleware to identify direct_mention and mention events.\\nIn single-team mode, this will pull the information from the Slack API at launch.\\nIn multi-team mode, this will use the `getBotUserByTeam` method passed to the constructor to pull the information from a developer-defined source.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 72,\n                      \"name\": \"activity\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An incoming message activity\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"Activity\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 219,\n                  \"character\": 33\n                }\n              ]\n            },\n            {\n              \"id\": 73,\n              \"name\": \"getInstallLink\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 74,\n                  \"name\": \"getInstallLink\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Get the oauth link for this bot, based on the clientId and scopes passed in to the constructor.\",\n                    \"text\": \"An example using Botkit's internal webserver to configure the /install route:\\n\\n```javascript\\ncontroller.webserver.get('/install', (req, res) => {\\n res.redirect(controller.adapter.getInstallLink());\\n});\\n```\\n\",\n                    \"returns\": \"A url pointing to the first step in Slack's oauth flow.\\n\"\n                  },\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"string\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 250,\n                  \"character\": 25\n                }\n              ]\n            },\n            {\n              \"id\": 100,\n              \"name\": \"processActivity\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 101,\n                  \"name\": \"processActivity\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Accept an incoming webhook request and convert it into a TurnContext which can be processed by the bot's logic.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 102,\n                      \"name\": \"req\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A request object from Restify or Express\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 103,\n                      \"name\": \"res\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A response object from Restify or Express\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 104,\n                      \"name\": \"logic\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A bot logic function in the form `async(context) => { ... }`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 105,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 106,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 107,\n                                  \"name\": \"context\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"name\": \"TurnContext\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"void\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"slack_adapter.ts\",\n                              \"line\": 513,\n                              \"character\": 49\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 513,\n                  \"character\": 32\n                }\n              ]\n            },\n            {\n              \"id\": 81,\n              \"name\": \"sendActivities\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 82,\n                  \"name\": \"sendActivities\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Standard BotBuilder adapter method to send a message from the bot to the messaging API.\\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#sendactivities).\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 83,\n                      \"name\": \"context\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A TurnContext representing the current incoming message and environment.\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"TurnContext\"\n                      }\n                    },\n                    {\n                      \"id\": 84,\n                      \"name\": \"activities\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An array of outgoing activities to be sent back to the messaging API.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"reference\",\n                          \"typeArguments\": [\n                            {\n                              \"type\": \"reference\",\n                              \"name\": \"Activity\"\n                            }\n                          ],\n                          \"name\": \"Partial\"\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"reference\",\n                          \"name\": \"ResourceResponse\"\n                        }\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 361,\n                  \"character\": 31\n                }\n              ]\n            },\n            {\n              \"id\": 85,\n              \"name\": \"updateActivity\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 86,\n                  \"name\": \"updateActivity\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Standard BotBuilder adapter method to update a previous message with new content.\\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#updateactivity).\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 87,\n                      \"name\": \"context\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A TurnContext representing the current incoming message and environment.\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"TurnContext\"\n                      }\n                    },\n                    {\n                      \"id\": 88,\n                      \"name\": \"activity\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"The updated activity in the form `{id: <id of activity to update>, ...}`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"Activity\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 406,\n                  \"character\": 31\n                }\n              ]\n            },\n            {\n              \"id\": 75,\n              \"name\": \"validateOauthCode\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 76,\n                  \"name\": \"validateOauthCode\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Validates an oauth v2 code sent by Slack during the install process.\",\n                    \"text\": \"An example using Botkit's internal webserver to configure the /install/auth route:\\n\\n```javascript\\ncontroller.webserver.get('/install/auth', async (req, res) => {\\n     try {\\n         const results = await controller.adapter.validateOauthCode(req.query.code);\\n         // make sure to capture the token and bot user id by team id...\\n         const team_id = results.team.id;\\n         const token = results.access_token;\\n         const bot_user = results.bot_user_id;\\n         // store these values in a way they'll be retrievable with getBotUserByTeam and getTokenForTeam\\n     } catch (err) {\\n          console.error('OAUTH ERROR:', err);\\n          res.status(401);\\n          res.send(err.message);\\n     }\\n});\\n```\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 77,\n                      \"name\": \"code\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"the value found in `req.query.code` as part of Slack's response to the oauth flow.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 291,\n                  \"character\": 34\n                }\n              ]\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Constructors\",\n              \"kind\": 512,\n              \"children\": [\n                64\n              ]\n            },\n            {\n              \"title\": \"Methods\",\n              \"kind\": 2048,\n              \"children\": [\n                78,\n                93,\n                89,\n                67,\n                70,\n                73,\n                100,\n                81,\n                85,\n                75\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"slack_adapter.ts\",\n              \"line\": 19,\n              \"character\": 25\n            }\n          ],\n          \"extendedTypes\": [\n            {\n              \"type\": \"intrinsic\",\n              \"name\": \"any\"\n            }\n          ],\n          \"props\": [],\n          \"methods\": [\n            {\n              \"id\": 78,\n              \"name\": \"activityToSlack\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 79,\n                  \"name\": \"activityToSlack\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Formats a BotBuilder activity into an outgoing Slack message.\",\n                    \"returns\": \"a Slack message object with {text, attachments, channel, thread_ts} as well as any fields found in activity.channelData\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 80,\n                      \"name\": \"activity\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A BotBuilder Activity object\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"Activity\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"any\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 317,\n                  \"character\": 26\n                }\n              ]\n            },\n            {\n              \"id\": 93,\n              \"name\": \"continueConversation\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 94,\n                  \"name\": \"continueConversation\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Standard BotBuilder adapter method for continuing an existing conversation based on a conversation reference.\\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#continueconversation)\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 95,\n                      \"name\": \"reference\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A conversation reference to be applied to future messages.\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"ConversationReference\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    },\n                    {\n                      \"id\": 96,\n                      \"name\": \"logic\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A bot logic function that will perform continuing action in the form `async(context) => { ... }`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 97,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 98,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 99,\n                                  \"name\": \"context\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"name\": \"TurnContext\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"void\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"slack_adapter.ts\",\n                              \"line\": 452,\n                              \"character\": 87\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 452,\n                  \"character\": 37\n                }\n              ]\n            },\n            {\n              \"id\": 89,\n              \"name\": \"deleteActivity\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 90,\n                  \"name\": \"deleteActivity\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Standard BotBuilder adapter method to delete a previous message.\\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#deleteactivity).\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 91,\n                      \"name\": \"context\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A TurnContext representing the current incoming message and environment.\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"TurnContext\"\n                      }\n                    },\n                    {\n                      \"id\": 92,\n                      \"name\": \"reference\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An object in the form `{activityId: <id of message to delete>, conversation: { id: <id of slack channel>}}`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"ConversationReference\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 429,\n                  \"character\": 31\n                }\n              ]\n            },\n            {\n              \"id\": 67,\n              \"name\": \"getAPI\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 68,\n                  \"name\": \"getAPI\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Get a Slack API client with the correct credentials based on the team identified in the incoming activity.\\nThis is used by many internal functions to get access to the Slack API, and is exposed as `bot.api` on any bot worker instances.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 69,\n                      \"name\": \"activity\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An incoming message activity\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"Activity\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"reference\",\n                        \"name\": \"WebClient\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 193,\n                  \"character\": 23\n                }\n              ]\n            },\n            {\n              \"id\": 70,\n              \"name\": \"getBotUserByTeam\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 71,\n                  \"name\": \"getBotUserByTeam\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Get the bot user id associated with the team on which an incoming activity originated. This is used internally by the SlackMessageTypeMiddleware to identify direct_mention and mention events.\\nIn single-team mode, this will pull the information from the Slack API at launch.\\nIn multi-team mode, this will use the `getBotUserByTeam` method passed to the constructor to pull the information from a developer-defined source.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 72,\n                      \"name\": \"activity\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An incoming message activity\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"Activity\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 219,\n                  \"character\": 33\n                }\n              ]\n            },\n            {\n              \"id\": 73,\n              \"name\": \"getInstallLink\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 74,\n                  \"name\": \"getInstallLink\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Get the oauth link for this bot, based on the clientId and scopes passed in to the constructor.\",\n                    \"text\": \"An example using Botkit's internal webserver to configure the /install route:\\n\\n```javascript\\ncontroller.webserver.get('/install', (req, res) => {\\n res.redirect(controller.adapter.getInstallLink());\\n});\\n```\\n\",\n                    \"returns\": \"A url pointing to the first step in Slack's oauth flow.\\n\"\n                  },\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"string\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 250,\n                  \"character\": 25\n                }\n              ]\n            },\n            {\n              \"id\": 100,\n              \"name\": \"processActivity\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 101,\n                  \"name\": \"processActivity\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Accept an incoming webhook request and convert it into a TurnContext which can be processed by the bot's logic.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 102,\n                      \"name\": \"req\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A request object from Restify or Express\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 103,\n                      \"name\": \"res\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A response object from Restify or Express\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 104,\n                      \"name\": \"logic\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A bot logic function in the form `async(context) => { ... }`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 105,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 106,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 107,\n                                  \"name\": \"context\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"name\": \"TurnContext\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"void\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"slack_adapter.ts\",\n                              \"line\": 513,\n                              \"character\": 49\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 513,\n                  \"character\": 32\n                }\n              ]\n            },\n            {\n              \"id\": 81,\n              \"name\": \"sendActivities\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 82,\n                  \"name\": \"sendActivities\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Standard BotBuilder adapter method to send a message from the bot to the messaging API.\\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#sendactivities).\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 83,\n                      \"name\": \"context\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A TurnContext representing the current incoming message and environment.\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"TurnContext\"\n                      }\n                    },\n                    {\n                      \"id\": 84,\n                      \"name\": \"activities\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An array of outgoing activities to be sent back to the messaging API.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"reference\",\n                          \"typeArguments\": [\n                            {\n                              \"type\": \"reference\",\n                              \"name\": \"Activity\"\n                            }\n                          ],\n                          \"name\": \"Partial\"\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"reference\",\n                          \"name\": \"ResourceResponse\"\n                        }\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 361,\n                  \"character\": 31\n                }\n              ]\n            },\n            {\n              \"id\": 85,\n              \"name\": \"updateActivity\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 86,\n                  \"name\": \"updateActivity\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Standard BotBuilder adapter method to update a previous message with new content.\\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#updateactivity).\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 87,\n                      \"name\": \"context\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A TurnContext representing the current incoming message and environment.\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"TurnContext\"\n                      }\n                    },\n                    {\n                      \"id\": 88,\n                      \"name\": \"activity\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"The updated activity in the form `{id: <id of activity to update>, ...}`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"Activity\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 406,\n                  \"character\": 31\n                }\n              ]\n            },\n            {\n              \"id\": 75,\n              \"name\": \"validateOauthCode\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 76,\n                  \"name\": \"validateOauthCode\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Validates an oauth v2 code sent by Slack during the install process.\",\n                    \"text\": \"An example using Botkit's internal webserver to configure the /install/auth route:\\n\\n```javascript\\ncontroller.webserver.get('/install/auth', async (req, res) => {\\n     try {\\n         const results = await controller.adapter.validateOauthCode(req.query.code);\\n         // make sure to capture the token and bot user id by team id...\\n         const team_id = results.team.id;\\n         const token = results.access_token;\\n         const bot_user = results.bot_user_id;\\n         // store these values in a way they'll be retrievable with getBotUserByTeam and getTokenForTeam\\n     } catch (err) {\\n          console.error('OAUTH ERROR:', err);\\n          res.status(401);\\n          res.send(err.message);\\n     }\\n});\\n```\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 77,\n                      \"name\": \"code\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"the value found in `req.query.code` as part of Slack's response to the oauth flow.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 291,\n                  \"character\": 34\n                }\n              ]\n            }\n          ],\n          \"constructors\": [\n            {\n              \"id\": 64,\n              \"name\": \"constructor\",\n              \"kind\": 512,\n              \"kindString\": \"Constructor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Create a Slack adapter.\",\n                \"text\": \"The SlackAdapter can be used in 2 modes:\\n     * As an \\\"[internal integration](https://api.slack.com/internal-integrations) connected to a single Slack workspace\\n     * As a \\\"[Slack app](https://api.slack.com/slack-apps) that uses oauth to connect to multiple workspaces and can be submitted to the Slack app.\\n\\n[Read here for more information about all the ways to configure the SlackAdapter &rarr;](../../botbuilder-adapter-slack/readme.md).\\n\\nUse with Botkit:\\n```javascript\\nconst adapter = new SlackAdapter({\\n     clientSigningSecret: process.env.CLIENT_SIGNING_SECRET,\\n     botToken: process.env.BOT_TOKEN\\n});\\nconst controller = new Botkit({\\n     adapter: adapter,\\n     // ... other configuration options\\n});\\n```\\n\\nUse with BotBuilder:\\n```javascript\\nconst adapter = new SlackAdapter({\\n     clientSigningSecret: process.env.CLIENT_SIGNING_SECRET,\\n     botToken: process.env.BOT_TOKEN\\n});\\n// set up restify...\\nconst server = restify.createServer();\\nserver.use(restify.plugins.bodyParser());\\nserver.post('/api/messages', (req, res) => {\\n     adapter.processActivity(req, res, async(context) => {\\n         // do your bot logic here!\\n     });\\n});\\n```\\n\\nUse in \\\"Slack app\\\" multi-team mode:\\n```javascript\\nconst adapter = new SlackAdapter({\\n    clientSigningSecret: process.env.CLIENT_SIGNING_SECRET,\\n    clientId: process.env.CLIENT_ID, // oauth client id\\n    clientSecret: process.env.CLIENT_SECRET, // oauth client secret\\n    scopes: ['bot'], // oauth scopes requested\\n    oauthVersion: 'v1',\\n    redirectUri: process.env.REDIRECT_URI, // url to redirect post login defaults to `https://<mydomain>/install/auth`\\n    getTokenForTeam: async(team_id) => Promise<string>, // function that returns a token based on team id\\n    getBotUserByTeam: async(team_id) => Promise<string>, // function that returns a bot's user id based on team id\\n});\\n```\\n\"\n              },\n              \"signatures\": [\n                {\n                  \"id\": 65,\n                  \"name\": \"new SlackAdapter\",\n                  \"kind\": 16384,\n                  \"kindString\": \"Constructor signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Create a Slack adapter.\",\n                    \"text\": \"The SlackAdapter can be used in 2 modes:\\n     * As an \\\"[internal integration](https://api.slack.com/internal-integrations) connected to a single Slack workspace\\n     * As a \\\"[Slack app](https://api.slack.com/slack-apps) that uses oauth to connect to multiple workspaces and can be submitted to the Slack app.\\n\\n[Read here for more information about all the ways to configure the SlackAdapter &rarr;](../../botbuilder-adapter-slack/readme.md).\\n\\nUse with Botkit:\\n```javascript\\nconst adapter = new SlackAdapter({\\n     clientSigningSecret: process.env.CLIENT_SIGNING_SECRET,\\n     botToken: process.env.BOT_TOKEN\\n});\\nconst controller = new Botkit({\\n     adapter: adapter,\\n     // ... other configuration options\\n});\\n```\\n\\nUse with BotBuilder:\\n```javascript\\nconst adapter = new SlackAdapter({\\n     clientSigningSecret: process.env.CLIENT_SIGNING_SECRET,\\n     botToken: process.env.BOT_TOKEN\\n});\\n// set up restify...\\nconst server = restify.createServer();\\nserver.use(restify.plugins.bodyParser());\\nserver.post('/api/messages', (req, res) => {\\n     adapter.processActivity(req, res, async(context) => {\\n         // do your bot logic here!\\n     });\\n});\\n```\\n\\nUse in \\\"Slack app\\\" multi-team mode:\\n```javascript\\nconst adapter = new SlackAdapter({\\n    clientSigningSecret: process.env.CLIENT_SIGNING_SECRET,\\n    clientId: process.env.CLIENT_ID, // oauth client id\\n    clientSecret: process.env.CLIENT_SECRET, // oauth client secret\\n    scopes: ['bot'], // oauth scopes requested\\n    oauthVersion: 'v1',\\n    redirectUri: process.env.REDIRECT_URI, // url to redirect post login defaults to `https://<mydomain>/install/auth`\\n    getTokenForTeam: async(team_id) => Promise<string>, // function that returns a token based on team id\\n    getBotUserByTeam: async(team_id) => Promise<string>, // function that returns a bot's user id based on team id\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 66,\n                      \"name\": \"options\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"An object containing API credentials, a webhook verification token and other options\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 108,\n                        \"name\": \"SlackAdapterOptions\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 60,\n                    \"name\": \"SlackAdapter\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 42,\n                  \"character\": 42\n                }\n              ]\n            }\n          ]\n        },\n        {\n          \"id\": 2,\n          \"name\": \"SlackBotWorker\",\n          \"kind\": 128,\n          \"kindString\": \"Class\",\n          \"flags\": {\n            \"isExported\": true,\n            \"isExternal\": true\n          },\n          \"comment\": {\n            \"shortText\": \"This is a specialized version of [Botkit's core BotWorker class](core.md#BotWorker) that includes additional methods for interacting with Slack.\\nIt includes all functionality from the base class, as well as the extension methods below.\",\n            \"text\": \"When using the SlackAdapter with Botkit, all `bot` objects passed to handler functions will include these extensions.\\n\"\n          },\n          \"children\": [\n            {\n              \"id\": 4,\n              \"name\": \"constructor\",\n              \"kind\": 512,\n              \"kindString\": \"Constructor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Reserved for use internally by Botkit's `controller.spawn()`, this class is used to create a BotWorker instance that can send messages, replies, and make other API calls.\",\n                \"text\": \"It is possible to spawn a bot instance by passing in the Slack workspace ID of a team that has installed the app.\\nUse this in concert with [startPrivateConversation()](#startPrivateConversation) and [changeContext()](core.md#changecontext) to start conversations\\nor send proactive alerts to users on a schedule or in response to external events.\\n\\n\\n```javascript\\n// spawn a bot for a given team.\\nlet bot = await controller.spawn('T0123456');\\n\\n// start a 1:1 with a specific user\\nawait bot.startPrivateConversation('U0123456');\\n\\n// send a message\\nawait bot.say('Hi user');\\n```\\n\"\n              },\n              \"signatures\": [\n                {\n                  \"id\": 5,\n                  \"name\": \"new SlackBotWorker\",\n                  \"kind\": 16384,\n                  \"kindString\": \"Constructor signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Reserved for use internally by Botkit's `controller.spawn()`, this class is used to create a BotWorker instance that can send messages, replies, and make other API calls.\",\n                    \"text\": \"It is possible to spawn a bot instance by passing in the Slack workspace ID of a team that has installed the app.\\nUse this in concert with [startPrivateConversation()](#startPrivateConversation) and [changeContext()](core.md#changecontext) to start conversations\\nor send proactive alerts to users on a schedule or in response to external events.\\n\\n\\n```javascript\\n// spawn a bot for a given team.\\nlet bot = await controller.spawn('T0123456');\\n\\n// start a 1:1 with a specific user\\nawait bot.startPrivateConversation('U0123456');\\n\\n// send a message\\nawait bot.say('Hi user');\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 6,\n                      \"name\": \"botkit\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"The Botkit controller object responsible for spawning this bot worker\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"Botkit\"\n                      }\n                    },\n                    {\n                      \"id\": 7,\n                      \"name\": \"config\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"Normally, a DialogContext object.  Can also be the id of a team.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 2,\n                    \"name\": \"SlackBotWorker\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 23,\n                  \"character\": 26\n                }\n              ]\n            },\n            {\n              \"id\": 3,\n              \"name\": \"api\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A copy of hte Slack WebClient giving, giving access to all of Slack's APIs via `let res = await bot.api.object.method(params);`\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 23,\n                  \"character\": 14\n                }\n              ],\n              \"type\": {\n                \"type\": \"reference\",\n                \"name\": \"WebClient\"\n              }\n            },\n            {\n              \"id\": 56,\n              \"name\": \"deleteMessage\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 57,\n                  \"name\": \"deleteMessage\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Delete an existing message.\",\n                    \"text\": \"```javascript\\n// send a reply, capture the results\\nlet sent = await bot.reply(message,'this is my original reply...');\\n\\n// delete the sent message using the sent.id field\\nawait bot.deleteMessage(sent);\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 58,\n                      \"name\": \"update\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An object in the form of `{id: <id of message to delete>, conversation: { id: <channel of message> }}`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"BotkitMessage\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 358,\n                  \"character\": 30\n                }\n              ]\n            },\n            {\n              \"id\": 40,\n              \"name\": \"dialogError\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 41,\n                  \"name\": \"dialogError\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Return 1 or more error to a `dialog_submission` event that will be displayed as form validation errors.\\nEach error must be mapped to the name of an input in the dialog.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 42,\n                      \"name\": \"errors\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"1 or more objects in form {name: string, error: string}\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"reflection\",\n                            \"declaration\": {\n                              \"id\": 43,\n                              \"name\": \"__type\",\n                              \"kind\": 65536,\n                              \"kindString\": \"Type literal\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"children\": [\n                                {\n                                  \"id\": 45,\n                                  \"name\": \"error\",\n                                  \"kind\": 32,\n                                  \"kindString\": \"Variable\",\n                                  \"flags\": {\n                                    \"isExported\": true,\n                                    \"isExternal\": true\n                                  },\n                                  \"sources\": [\n                                    {\n                                      \"fileName\": \"botworker.ts\",\n                                      \"line\": 296,\n                                      \"character\": 51\n                                    }\n                                  ],\n                                  \"type\": {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"string\"\n                                  }\n                                },\n                                {\n                                  \"id\": 44,\n                                  \"name\": \"name\",\n                                  \"kind\": 32,\n                                  \"kindString\": \"Variable\",\n                                  \"flags\": {\n                                    \"isExported\": true,\n                                    \"isExternal\": true\n                                  },\n                                  \"sources\": [\n                                    {\n                                      \"fileName\": \"botworker.ts\",\n                                      \"line\": 296,\n                                      \"character\": 36\n                                    }\n                                  ],\n                                  \"type\": {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"string\"\n                                  }\n                                }\n                              ],\n                              \"groups\": [\n                                {\n                                  \"title\": \"Variables\",\n                                  \"kind\": 32,\n                                  \"children\": [\n                                    45,\n                                    44\n                                  ]\n                                }\n                              ],\n                              \"sources\": [\n                                {\n                                  \"fileName\": \"botworker.ts\",\n                                  \"line\": 296,\n                                  \"character\": 30\n                                }\n                              ]\n                            }\n                          },\n                          {\n                            \"type\": \"array\",\n                            \"elementType\": {\n                              \"type\": \"reflection\",\n                              \"declaration\": {\n                                \"id\": 46,\n                                \"name\": \"__type\",\n                                \"kind\": 65536,\n                                \"kindString\": \"Type literal\",\n                                \"flags\": {\n                                  \"isExported\": true\n                                },\n                                \"children\": [\n                                  {\n                                    \"id\": 48,\n                                    \"name\": \"error\",\n                                    \"kind\": 32,\n                                    \"kindString\": \"Variable\",\n                                    \"flags\": {\n                                      \"isExported\": true,\n                                      \"isExternal\": true\n                                    },\n                                    \"sources\": [\n                                      {\n                                        \"fileName\": \"botworker.ts\",\n                                        \"line\": 296,\n                                        \"character\": 84\n                                      }\n                                    ],\n                                    \"type\": {\n                                      \"type\": \"intrinsic\",\n                                      \"name\": \"string\"\n                                    }\n                                  },\n                                  {\n                                    \"id\": 47,\n                                    \"name\": \"name\",\n                                    \"kind\": 32,\n                                    \"kindString\": \"Variable\",\n                                    \"flags\": {\n                                      \"isExported\": true,\n                                      \"isExternal\": true\n                                    },\n                                    \"sources\": [\n                                      {\n                                        \"fileName\": \"botworker.ts\",\n                                        \"line\": 296,\n                                        \"character\": 69\n                                      }\n                                    ],\n                                    \"type\": {\n                                      \"type\": \"intrinsic\",\n                                      \"name\": \"string\"\n                                    }\n                                  }\n                                ],\n                                \"groups\": [\n                                  {\n                                    \"title\": \"Variables\",\n                                    \"kind\": 32,\n                                    \"children\": [\n                                      48,\n                                      47\n                                    ]\n                                  }\n                                ],\n                                \"sources\": [\n                                  {\n                                    \"fileName\": \"botworker.ts\",\n                                    \"line\": 296,\n                                    \"character\": 62\n                                  }\n                                ]\n                              }\n                            }\n                          }\n                        ]\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 296,\n                  \"character\": 22\n                }\n              ]\n            },\n            {\n              \"id\": 24,\n              \"name\": \"replyEphemeral\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 25,\n                  \"name\": \"replyEphemeral\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Like bot.reply, but sent as an \\\"ephemeral\\\" message meaning only the recipient can see it.\\nUses [chat.postEphemeral](https://api.slack.com/methods/chat.postEphemeral)\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 26,\n                      \"name\": \"src\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"an incoming message object\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 27,\n                      \"name\": \"resp\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"an outgoing message object (or part of one or just reply text)\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 207,\n                  \"character\": 31\n                }\n              ]\n            },\n            {\n              \"id\": 20,\n              \"name\": \"replyInThread\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 21,\n                  \"name\": \"replyInThread\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Like bot.reply, but as a threaded response to the incoming message rather than a new message in the main channel.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 22,\n                      \"name\": \"src\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"an incoming message object\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 23,\n                      \"name\": \"resp\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"an outgoing message object (or part of one or just reply text)\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 194,\n                  \"character\": 30\n                }\n              ]\n            },\n            {\n              \"id\": 36,\n              \"name\": \"replyInteractive\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 37,\n                  \"name\": \"replyInteractive\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Like bot.reply, but used to respond to an `interactive_message` event and cause the original message to be replaced with a new one.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 38,\n                      \"name\": \"src\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"an incoming message object of type `interactive_message`\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 39,\n                      \"name\": \"resp\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"a new or modified message that will replace the original one\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 254,\n                  \"character\": 33\n                }\n              ]\n            },\n            {\n              \"id\": 32,\n              \"name\": \"replyPrivate\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 33,\n                  \"name\": \"replyPrivate\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Like bot.reply, but used to send an immediate private reply to a /slash command.\\nThe message in `resp` will be displayed only to the person who executed the slash command.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 34,\n                      \"name\": \"src\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"an incoming message object of type `slash_command`\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 35,\n                      \"name\": \"resp\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"an outgoing message object (or part of one or just reply text)\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 240,\n                  \"character\": 29\n                }\n              ]\n            },\n            {\n              \"id\": 28,\n              \"name\": \"replyPublic\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 29,\n                  \"name\": \"replyPublic\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Like bot.reply, but used to send an immediate public reply to a /slash command.\\nThe message in `resp` will be displayed to everyone in the channel.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 30,\n                      \"name\": \"src\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"an incoming message object of type `slash_command`\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 31,\n                      \"name\": \"resp\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"an outgoing message object (or part of one or just reply text)\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 227,\n                  \"character\": 28\n                }\n              ]\n            },\n            {\n              \"id\": 49,\n              \"name\": \"replyWithDialog\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 50,\n                  \"name\": \"replyWithDialog\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Reply to a button click with a request to open a dialog.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 51,\n                      \"name\": \"src\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An incoming `interactive_callback` event containing a `trigger_id` field\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 52,\n                      \"name\": \"dialog_obj\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A dialog, as created using [SlackDialog](#SlackDialog) or [authored to this spec](https://api.slack.com/dialogs).\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"Dialog\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 313,\n                  \"character\": 32\n                }\n              ]\n            },\n            {\n              \"id\": 11,\n              \"name\": \"startConversationInChannel\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 12,\n                  \"name\": \"startConversationInChannel\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Switch a bot's context into a different channel.\\nAfter calling this method, messages sent with `bot.say` and any dialogs started with `bot.beginDialog` will occur in this new context.\",\n                    \"text\": \"```javascript\\ncontroller.hears('dm me', 'message', async(bot, message) => {\\n\\n     // switch to the channel specified in SLACK_CHANNEL_ID\\n     // if just using bot.say and not starting a dialog, can use a fake value for user id.\\n     await bot.startConversationInChannel(SLACK_CHANNEL_ID, message.user);\\n\\n     // say hello\\n     await bot.say('Shall we discuss this matter over here?');\\n     // ... continue...\\n     await bot.beginDialog(ANOTHER_DIALOG);\\n\\n});\\n```\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 13,\n                      \"name\": \"channelId\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A Slack channel id, like one found in `message.channel`\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 14,\n                      \"name\": \"userId\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A Slack user id, like one found in `message.user` or in a `<@mention>`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 143,\n                  \"character\": 43\n                }\n              ]\n            },\n            {\n              \"id\": 15,\n              \"name\": \"startConversationInThread\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 16,\n                  \"name\": \"startConversationInThread\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Switch a bot's context into a specific sub-thread within a channel.\\nAfter calling this method, messages sent with `bot.say` and any dialogs started with `bot.beginDialog` will occur in this new context.\",\n                    \"text\": \"```javascript\\ncontroller.hears('in a thread', 'message', async(bot, message) => {\\n\\n     // branch from the main channel into a side thread associated with this message\\n     await bot.startConversationInThread(message.channel, message.user, message.ts);\\n\\n     // say hello\\n     await bot.say(`Let's handle this offline...`);\\n     // ... continue...\\n     await bot.beginDialog(OFFLINE_DIALOG);\\n\\n});\\n```\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 17,\n                      \"name\": \"channelId\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A Slack channel id, like one found in `message.channel`\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 18,\n                      \"name\": \"userId\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A Slack user id, like one found in `message.user` or in a `<@mention>`\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 19,\n                      \"name\": \"thread_ts\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A thread_ts value found in the `message.thread_ts` or `message.ts` field.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 176,\n                  \"character\": 42\n                }\n              ]\n            },\n            {\n              \"id\": 8,\n              \"name\": \"startPrivateConversation\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 9,\n                  \"name\": \"startPrivateConversation\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Switch a bot's context to a 1:1 private message channel with a specific user.\\nAfter calling this method, messages sent with `bot.say` and any dialogs started with `bot.beginDialog` will occur in this new context.\",\n                    \"text\": \"```javascript\\ncontroller.hears('dm me', 'message', async(bot, message) => {\\n\\n     // switch to a 1:1 conversation in a DM\\n     await bot.startPrivateConversation(message.user);\\n\\n     // say hello\\n     await bot.say('We are in private now...');\\n     await bot.beginDialog(MY_PRIVATE_DIALOG);\\n\\n});\\n```\\n\\nAlso useful when sending pro-active messages such as those sent on a schedule or in response to external events:\\n```javascript\\n// Spawn a worker with a Slack team id.\\nlet bot = await controller.spawn(SLACK_TEAM_ID);\\n\\n// Set the context for the bot's next action...\\nawait bot.startPrivateConversation(SLACK_ADMIN_USER);\\n\\n// Begin a dialog in the 1:1 context\\nawait bot.beginDialog(ALERT_DIALOG);\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 10,\n                      \"name\": \"userId\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A Slack user id, like one found in `message.user` or in a `<@mention>`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 101,\n                  \"character\": 41\n                }\n              ]\n            },\n            {\n              \"id\": 53,\n              \"name\": \"updateMessage\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 54,\n                  \"name\": \"updateMessage\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Update an existing message with new content.\",\n                    \"text\": \"```javascript\\n// send a reply, capture the results\\nlet sent = await bot.reply(message,'this is my original reply...');\\n\\n// update the sent message using the sent.id field\\nawait bot.updateMessage({\\n     text: 'this is an update!',\\n     ...sent\\n})\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 55,\n                      \"name\": \"update\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An object in the form `{id: <id of message to update>, conversation: { id: <channel> }, text: <new text>, card: <array of card objects>}`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"BotkitMessage\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 338,\n                  \"character\": 30\n                }\n              ]\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Constructors\",\n              \"kind\": 512,\n              \"children\": [\n                4\n              ]\n            },\n            {\n              \"title\": \"Properties\",\n              \"kind\": 1024,\n              \"children\": [\n                3\n              ]\n            },\n            {\n              \"title\": \"Methods\",\n              \"kind\": 2048,\n              \"children\": [\n                56,\n                40,\n                24,\n                20,\n                36,\n                32,\n                28,\n                49,\n                11,\n                15,\n                8,\n                53\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"botworker.ts\",\n              \"line\": 19,\n              \"character\": 27\n            }\n          ],\n          \"extendedTypes\": [\n            {\n              \"type\": \"intrinsic\",\n              \"name\": \"any\"\n            }\n          ],\n          \"props\": [\n            {\n              \"id\": 3,\n              \"name\": \"api\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A copy of hte Slack WebClient giving, giving access to all of Slack's APIs via `let res = await bot.api.object.method(params);`\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 23,\n                  \"character\": 14\n                }\n              ],\n              \"type\": {\n                \"type\": \"reference\",\n                \"name\": \"WebClient\"\n              }\n            }\n          ],\n          \"methods\": [\n            {\n              \"id\": 56,\n              \"name\": \"deleteMessage\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 57,\n                  \"name\": \"deleteMessage\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Delete an existing message.\",\n                    \"text\": \"```javascript\\n// send a reply, capture the results\\nlet sent = await bot.reply(message,'this is my original reply...');\\n\\n// delete the sent message using the sent.id field\\nawait bot.deleteMessage(sent);\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 58,\n                      \"name\": \"update\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An object in the form of `{id: <id of message to delete>, conversation: { id: <channel of message> }}`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"BotkitMessage\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 358,\n                  \"character\": 30\n                }\n              ]\n            },\n            {\n              \"id\": 40,\n              \"name\": \"dialogError\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 41,\n                  \"name\": \"dialogError\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Return 1 or more error to a `dialog_submission` event that will be displayed as form validation errors.\\nEach error must be mapped to the name of an input in the dialog.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 42,\n                      \"name\": \"errors\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"1 or more objects in form {name: string, error: string}\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"reflection\",\n                            \"declaration\": {\n                              \"id\": 43,\n                              \"name\": \"__type\",\n                              \"kind\": 65536,\n                              \"kindString\": \"Type literal\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"children\": [\n                                {\n                                  \"id\": 45,\n                                  \"name\": \"error\",\n                                  \"kind\": 32,\n                                  \"kindString\": \"Variable\",\n                                  \"flags\": {\n                                    \"isExported\": true,\n                                    \"isExternal\": true\n                                  },\n                                  \"sources\": [\n                                    {\n                                      \"fileName\": \"botworker.ts\",\n                                      \"line\": 296,\n                                      \"character\": 51\n                                    }\n                                  ],\n                                  \"type\": {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"string\"\n                                  }\n                                },\n                                {\n                                  \"id\": 44,\n                                  \"name\": \"name\",\n                                  \"kind\": 32,\n                                  \"kindString\": \"Variable\",\n                                  \"flags\": {\n                                    \"isExported\": true,\n                                    \"isExternal\": true\n                                  },\n                                  \"sources\": [\n                                    {\n                                      \"fileName\": \"botworker.ts\",\n                                      \"line\": 296,\n                                      \"character\": 36\n                                    }\n                                  ],\n                                  \"type\": {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"string\"\n                                  }\n                                }\n                              ],\n                              \"groups\": [\n                                {\n                                  \"title\": \"Variables\",\n                                  \"kind\": 32,\n                                  \"children\": [\n                                    45,\n                                    44\n                                  ]\n                                }\n                              ],\n                              \"sources\": [\n                                {\n                                  \"fileName\": \"botworker.ts\",\n                                  \"line\": 296,\n                                  \"character\": 30\n                                }\n                              ]\n                            }\n                          },\n                          {\n                            \"type\": \"array\",\n                            \"elementType\": {\n                              \"type\": \"reflection\",\n                              \"declaration\": {\n                                \"id\": 46,\n                                \"name\": \"__type\",\n                                \"kind\": 65536,\n                                \"kindString\": \"Type literal\",\n                                \"flags\": {\n                                  \"isExported\": true\n                                },\n                                \"children\": [\n                                  {\n                                    \"id\": 48,\n                                    \"name\": \"error\",\n                                    \"kind\": 32,\n                                    \"kindString\": \"Variable\",\n                                    \"flags\": {\n                                      \"isExported\": true,\n                                      \"isExternal\": true\n                                    },\n                                    \"sources\": [\n                                      {\n                                        \"fileName\": \"botworker.ts\",\n                                        \"line\": 296,\n                                        \"character\": 84\n                                      }\n                                    ],\n                                    \"type\": {\n                                      \"type\": \"intrinsic\",\n                                      \"name\": \"string\"\n                                    }\n                                  },\n                                  {\n                                    \"id\": 47,\n                                    \"name\": \"name\",\n                                    \"kind\": 32,\n                                    \"kindString\": \"Variable\",\n                                    \"flags\": {\n                                      \"isExported\": true,\n                                      \"isExternal\": true\n                                    },\n                                    \"sources\": [\n                                      {\n                                        \"fileName\": \"botworker.ts\",\n                                        \"line\": 296,\n                                        \"character\": 69\n                                      }\n                                    ],\n                                    \"type\": {\n                                      \"type\": \"intrinsic\",\n                                      \"name\": \"string\"\n                                    }\n                                  }\n                                ],\n                                \"groups\": [\n                                  {\n                                    \"title\": \"Variables\",\n                                    \"kind\": 32,\n                                    \"children\": [\n                                      48,\n                                      47\n                                    ]\n                                  }\n                                ],\n                                \"sources\": [\n                                  {\n                                    \"fileName\": \"botworker.ts\",\n                                    \"line\": 296,\n                                    \"character\": 62\n                                  }\n                                ]\n                              }\n                            }\n                          }\n                        ]\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 296,\n                  \"character\": 22\n                }\n              ]\n            },\n            {\n              \"id\": 24,\n              \"name\": \"replyEphemeral\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 25,\n                  \"name\": \"replyEphemeral\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Like bot.reply, but sent as an \\\"ephemeral\\\" message meaning only the recipient can see it.\\nUses [chat.postEphemeral](https://api.slack.com/methods/chat.postEphemeral)\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 26,\n                      \"name\": \"src\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"an incoming message object\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 27,\n                      \"name\": \"resp\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"an outgoing message object (or part of one or just reply text)\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 207,\n                  \"character\": 31\n                }\n              ]\n            },\n            {\n              \"id\": 20,\n              \"name\": \"replyInThread\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 21,\n                  \"name\": \"replyInThread\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Like bot.reply, but as a threaded response to the incoming message rather than a new message in the main channel.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 22,\n                      \"name\": \"src\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"an incoming message object\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 23,\n                      \"name\": \"resp\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"an outgoing message object (or part of one or just reply text)\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 194,\n                  \"character\": 30\n                }\n              ]\n            },\n            {\n              \"id\": 36,\n              \"name\": \"replyInteractive\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 37,\n                  \"name\": \"replyInteractive\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Like bot.reply, but used to respond to an `interactive_message` event and cause the original message to be replaced with a new one.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 38,\n                      \"name\": \"src\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"an incoming message object of type `interactive_message`\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 39,\n                      \"name\": \"resp\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"a new or modified message that will replace the original one\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 254,\n                  \"character\": 33\n                }\n              ]\n            },\n            {\n              \"id\": 32,\n              \"name\": \"replyPrivate\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 33,\n                  \"name\": \"replyPrivate\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Like bot.reply, but used to send an immediate private reply to a /slash command.\\nThe message in `resp` will be displayed only to the person who executed the slash command.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 34,\n                      \"name\": \"src\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"an incoming message object of type `slash_command`\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 35,\n                      \"name\": \"resp\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"an outgoing message object (or part of one or just reply text)\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 240,\n                  \"character\": 29\n                }\n              ]\n            },\n            {\n              \"id\": 28,\n              \"name\": \"replyPublic\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 29,\n                  \"name\": \"replyPublic\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Like bot.reply, but used to send an immediate public reply to a /slash command.\\nThe message in `resp` will be displayed to everyone in the channel.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 30,\n                      \"name\": \"src\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"an incoming message object of type `slash_command`\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 31,\n                      \"name\": \"resp\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"an outgoing message object (or part of one or just reply text)\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 227,\n                  \"character\": 28\n                }\n              ]\n            },\n            {\n              \"id\": 49,\n              \"name\": \"replyWithDialog\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 50,\n                  \"name\": \"replyWithDialog\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Reply to a button click with a request to open a dialog.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 51,\n                      \"name\": \"src\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An incoming `interactive_callback` event containing a `trigger_id` field\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 52,\n                      \"name\": \"dialog_obj\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A dialog, as created using [SlackDialog](#SlackDialog) or [authored to this spec](https://api.slack.com/dialogs).\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"Dialog\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 313,\n                  \"character\": 32\n                }\n              ]\n            },\n            {\n              \"id\": 11,\n              \"name\": \"startConversationInChannel\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 12,\n                  \"name\": \"startConversationInChannel\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Switch a bot's context into a different channel.\\nAfter calling this method, messages sent with `bot.say` and any dialogs started with `bot.beginDialog` will occur in this new context.\",\n                    \"text\": \"```javascript\\ncontroller.hears('dm me', 'message', async(bot, message) => {\\n\\n     // switch to the channel specified in SLACK_CHANNEL_ID\\n     // if just using bot.say and not starting a dialog, can use a fake value for user id.\\n     await bot.startConversationInChannel(SLACK_CHANNEL_ID, message.user);\\n\\n     // say hello\\n     await bot.say('Shall we discuss this matter over here?');\\n     // ... continue...\\n     await bot.beginDialog(ANOTHER_DIALOG);\\n\\n});\\n```\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 13,\n                      \"name\": \"channelId\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A Slack channel id, like one found in `message.channel`\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 14,\n                      \"name\": \"userId\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A Slack user id, like one found in `message.user` or in a `<@mention>`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 143,\n                  \"character\": 43\n                }\n              ]\n            },\n            {\n              \"id\": 15,\n              \"name\": \"startConversationInThread\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 16,\n                  \"name\": \"startConversationInThread\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Switch a bot's context into a specific sub-thread within a channel.\\nAfter calling this method, messages sent with `bot.say` and any dialogs started with `bot.beginDialog` will occur in this new context.\",\n                    \"text\": \"```javascript\\ncontroller.hears('in a thread', 'message', async(bot, message) => {\\n\\n     // branch from the main channel into a side thread associated with this message\\n     await bot.startConversationInThread(message.channel, message.user, message.ts);\\n\\n     // say hello\\n     await bot.say(`Let's handle this offline...`);\\n     // ... continue...\\n     await bot.beginDialog(OFFLINE_DIALOG);\\n\\n});\\n```\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 17,\n                      \"name\": \"channelId\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A Slack channel id, like one found in `message.channel`\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 18,\n                      \"name\": \"userId\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A Slack user id, like one found in `message.user` or in a `<@mention>`\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 19,\n                      \"name\": \"thread_ts\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A thread_ts value found in the `message.thread_ts` or `message.ts` field.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 176,\n                  \"character\": 42\n                }\n              ]\n            },\n            {\n              \"id\": 8,\n              \"name\": \"startPrivateConversation\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 9,\n                  \"name\": \"startPrivateConversation\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Switch a bot's context to a 1:1 private message channel with a specific user.\\nAfter calling this method, messages sent with `bot.say` and any dialogs started with `bot.beginDialog` will occur in this new context.\",\n                    \"text\": \"```javascript\\ncontroller.hears('dm me', 'message', async(bot, message) => {\\n\\n     // switch to a 1:1 conversation in a DM\\n     await bot.startPrivateConversation(message.user);\\n\\n     // say hello\\n     await bot.say('We are in private now...');\\n     await bot.beginDialog(MY_PRIVATE_DIALOG);\\n\\n});\\n```\\n\\nAlso useful when sending pro-active messages such as those sent on a schedule or in response to external events:\\n```javascript\\n// Spawn a worker with a Slack team id.\\nlet bot = await controller.spawn(SLACK_TEAM_ID);\\n\\n// Set the context for the bot's next action...\\nawait bot.startPrivateConversation(SLACK_ADMIN_USER);\\n\\n// Begin a dialog in the 1:1 context\\nawait bot.beginDialog(ALERT_DIALOG);\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 10,\n                      \"name\": \"userId\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A Slack user id, like one found in `message.user` or in a `<@mention>`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 101,\n                  \"character\": 41\n                }\n              ]\n            },\n            {\n              \"id\": 53,\n              \"name\": \"updateMessage\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 54,\n                  \"name\": \"updateMessage\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Update an existing message with new content.\",\n                    \"text\": \"```javascript\\n// send a reply, capture the results\\nlet sent = await bot.reply(message,'this is my original reply...');\\n\\n// update the sent message using the sent.id field\\nawait bot.updateMessage({\\n     text: 'this is an update!',\\n     ...sent\\n})\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 55,\n                      \"name\": \"update\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An object in the form `{id: <id of message to update>, conversation: { id: <channel> }, text: <new text>, card: <array of card objects>}`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"BotkitMessage\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 338,\n                  \"character\": 30\n                }\n              ]\n            }\n          ],\n          \"constructors\": [\n            {\n              \"id\": 4,\n              \"name\": \"constructor\",\n              \"kind\": 512,\n              \"kindString\": \"Constructor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Reserved for use internally by Botkit's `controller.spawn()`, this class is used to create a BotWorker instance that can send messages, replies, and make other API calls.\",\n                \"text\": \"It is possible to spawn a bot instance by passing in the Slack workspace ID of a team that has installed the app.\\nUse this in concert with [startPrivateConversation()](#startPrivateConversation) and [changeContext()](core.md#changecontext) to start conversations\\nor send proactive alerts to users on a schedule or in response to external events.\\n\\n\\n```javascript\\n// spawn a bot for a given team.\\nlet bot = await controller.spawn('T0123456');\\n\\n// start a 1:1 with a specific user\\nawait bot.startPrivateConversation('U0123456');\\n\\n// send a message\\nawait bot.say('Hi user');\\n```\\n\"\n              },\n              \"signatures\": [\n                {\n                  \"id\": 5,\n                  \"name\": \"new SlackBotWorker\",\n                  \"kind\": 16384,\n                  \"kindString\": \"Constructor signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Reserved for use internally by Botkit's `controller.spawn()`, this class is used to create a BotWorker instance that can send messages, replies, and make other API calls.\",\n                    \"text\": \"It is possible to spawn a bot instance by passing in the Slack workspace ID of a team that has installed the app.\\nUse this in concert with [startPrivateConversation()](#startPrivateConversation) and [changeContext()](core.md#changecontext) to start conversations\\nor send proactive alerts to users on a schedule or in response to external events.\\n\\n\\n```javascript\\n// spawn a bot for a given team.\\nlet bot = await controller.spawn('T0123456');\\n\\n// start a 1:1 with a specific user\\nawait bot.startPrivateConversation('U0123456');\\n\\n// send a message\\nawait bot.say('Hi user');\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 6,\n                      \"name\": \"botkit\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"The Botkit controller object responsible for spawning this bot worker\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"Botkit\"\n                      }\n                    },\n                    {\n                      \"id\": 7,\n                      \"name\": \"config\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"Normally, a DialogContext object.  Can also be the id of a team.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 2,\n                    \"name\": \"SlackBotWorker\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 23,\n                  \"character\": 26\n                }\n              ]\n            }\n          ]\n        },\n        {\n          \"id\": 140,\n          \"name\": \"SlackDialog\",\n          \"kind\": 128,\n          \"kindString\": \"Class\",\n          \"flags\": {\n            \"isExported\": true,\n            \"isExternal\": true\n          },\n          \"comment\": {\n            \"shortText\": \"Create a Slack Dialog object for use with [replyWithDialog()](#replyWithDialog).\",\n            \"text\": \"```javascript\\nlet dialog = new SlackDialog('My Dialog', 'callback_123', 'Save');\\ndialog.addText('Your full name', 'name').addEmail('Your email', 'email');\\ndialog.notifyOnCancel(true);\\nbot.replyWithDialog(message, dialog.asObject());\\n```\\n\\n\"\n          },\n          \"children\": [\n            {\n              \"id\": 141,\n              \"name\": \"constructor\",\n              \"kind\": 512,\n              \"kindString\": \"Constructor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Create a new dialog object\"\n              },\n              \"signatures\": [\n                {\n                  \"id\": 142,\n                  \"name\": \"new SlackDialog\",\n                  \"kind\": 16384,\n                  \"kindString\": \"Constructor signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Create a new dialog object\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 143,\n                      \"name\": \"title\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"Title of dialog\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 144,\n                      \"name\": \"callback_id\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"Callback id of dialog\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 145,\n                      \"name\": \"submit_label\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"Label for the submit button\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 146,\n                      \"name\": \"elements\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"An array of dialog elements\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 140,\n                    \"name\": \"SlackDialog\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_dialog.ts\",\n                  \"line\": 21,\n                  \"character\": 22\n                }\n              ]\n            },\n            {\n              \"id\": 169,\n              \"name\": \"addEmail\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 170,\n                  \"name\": \"addEmail\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Add an email input to the dialog\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 171,\n                      \"name\": \"label\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 172,\n                      \"name\": \"name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 173,\n                      \"name\": \"value\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 174,\n                      \"name\": \"options\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 140,\n                    \"name\": \"SlackDialog\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_dialog.ts\",\n                  \"line\": 120,\n                  \"character\": 19\n                }\n              ]\n            },\n            {\n              \"id\": 175,\n              \"name\": \"addNumber\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 176,\n                  \"name\": \"addNumber\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Add a number input to the dialog\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 177,\n                      \"name\": \"label\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 178,\n                      \"name\": \"name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 179,\n                      \"name\": \"value\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 180,\n                      \"name\": \"options\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 140,\n                    \"name\": \"SlackDialog\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_dialog.ts\",\n                  \"line\": 131,\n                  \"character\": 20\n                }\n              ]\n            },\n            {\n              \"id\": 200,\n              \"name\": \"addSelect\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 201,\n                  \"name\": \"addSelect\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Add a dropdown select input to the dialog\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 202,\n                      \"name\": \"label\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 203,\n                      \"name\": \"name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 204,\n                      \"name\": \"value\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"number\"\n                          },\n                          {\n                            \"type\": \"reference\",\n                            \"typeArguments\": [\n                              {\n                                \"type\": \"intrinsic\",\n                                \"name\": \"string\"\n                              },\n                              {\n                                \"type\": \"intrinsic\",\n                                \"name\": \"any\"\n                              }\n                            ],\n                            \"name\": \"Record\"\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"null\"\n                          }\n                        ]\n                      }\n                    },\n                    {\n                      \"id\": 205,\n                      \"name\": \"option_list\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"reflection\",\n                          \"declaration\": {\n                            \"id\": 206,\n                            \"name\": \"__type\",\n                            \"kind\": 65536,\n                            \"kindString\": \"Type literal\",\n                            \"flags\": {\n                              \"isExported\": true\n                            },\n                            \"children\": [\n                              {\n                                \"id\": 207,\n                                \"name\": \"label\",\n                                \"kind\": 32,\n                                \"kindString\": \"Variable\",\n                                \"flags\": {\n                                  \"isExported\": true,\n                                  \"isExternal\": true\n                                },\n                                \"sources\": [\n                                  {\n                                    \"fileName\": \"slack_dialog.ts\",\n                                    \"line\": 192,\n                                    \"character\": 123\n                                  }\n                                ],\n                                \"type\": {\n                                  \"type\": \"intrinsic\",\n                                  \"name\": \"string\"\n                                }\n                              },\n                              {\n                                \"id\": 208,\n                                \"name\": \"value\",\n                                \"kind\": 32,\n                                \"kindString\": \"Variable\",\n                                \"flags\": {\n                                  \"isExported\": true,\n                                  \"isExternal\": true\n                                },\n                                \"sources\": [\n                                  {\n                                    \"fileName\": \"slack_dialog.ts\",\n                                    \"line\": 192,\n                                    \"character\": 138\n                                  }\n                                ],\n                                \"type\": {\n                                  \"type\": \"union\",\n                                  \"types\": [\n                                    {\n                                      \"type\": \"intrinsic\",\n                                      \"name\": \"string\"\n                                    },\n                                    {\n                                      \"type\": \"intrinsic\",\n                                      \"name\": \"number\"\n                                    },\n                                    {\n                                      \"type\": \"reference\",\n                                      \"typeArguments\": [\n                                        {\n                                          \"type\": \"intrinsic\",\n                                          \"name\": \"string\"\n                                        },\n                                        {\n                                          \"type\": \"intrinsic\",\n                                          \"name\": \"any\"\n                                        }\n                                      ],\n                                      \"name\": \"Record\"\n                                    },\n                                    {\n                                      \"type\": \"intrinsic\",\n                                      \"name\": \"null\"\n                                    }\n                                  ]\n                                }\n                              }\n                            ],\n                            \"groups\": [\n                              {\n                                \"title\": \"Variables\",\n                                \"kind\": 32,\n                                \"children\": [\n                                  207,\n                                  208\n                                ]\n                              }\n                            ],\n                            \"sources\": [\n                              {\n                                \"fileName\": \"slack_dialog.ts\",\n                                \"line\": 192,\n                                \"character\": 115\n                              }\n                            ]\n                          }\n                        }\n                      }\n                    },\n                    {\n                      \"id\": 209,\n                      \"name\": \"options\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 140,\n                    \"name\": \"SlackDialog\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_dialog.ts\",\n                  \"line\": 192,\n                  \"character\": 20\n                }\n              ]\n            },\n            {\n              \"id\": 181,\n              \"name\": \"addTel\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 182,\n                  \"name\": \"addTel\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Add a telephone number input to the dialog\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 183,\n                      \"name\": \"label\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 184,\n                      \"name\": \"name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 185,\n                      \"name\": \"value\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 186,\n                      \"name\": \"options\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 140,\n                    \"name\": \"SlackDialog\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_dialog.ts\",\n                  \"line\": 142,\n                  \"character\": 17\n                }\n              ]\n            },\n            {\n              \"id\": 162,\n              \"name\": \"addText\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 163,\n                  \"name\": \"addText\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Add a text input to the dialog\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 164,\n                      \"name\": \"label\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"any\"\n                          }\n                        ]\n                      }\n                    },\n                    {\n                      \"id\": 165,\n                      \"name\": \"name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 166,\n                      \"name\": \"value\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 167,\n                      \"name\": \"options\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"any\"\n                          }\n                        ]\n                      }\n                    },\n                    {\n                      \"id\": 168,\n                      \"name\": \"subtype\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 140,\n                    \"name\": \"SlackDialog\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_dialog.ts\",\n                  \"line\": 94,\n                  \"character\": 18\n                }\n              ]\n            },\n            {\n              \"id\": 193,\n              \"name\": \"addTextarea\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 194,\n                  \"name\": \"addTextarea\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Add a text area input to the dialog\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 195,\n                      \"name\": \"label\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 196,\n                      \"name\": \"name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 197,\n                      \"name\": \"value\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 198,\n                      \"name\": \"options\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 199,\n                      \"name\": \"subtype\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 140,\n                    \"name\": \"SlackDialog\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_dialog.ts\",\n                  \"line\": 165,\n                  \"character\": 22\n                }\n              ]\n            },\n            {\n              \"id\": 187,\n              \"name\": \"addUrl\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 188,\n                  \"name\": \"addUrl\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Add a URL input to the dialog\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 189,\n                      \"name\": \"label\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 190,\n                      \"name\": \"name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 191,\n                      \"name\": \"value\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 192,\n                      \"name\": \"options\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 140,\n                    \"name\": \"SlackDialog\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_dialog.ts\",\n                  \"line\": 153,\n                  \"character\": 17\n                }\n              ]\n            },\n            {\n              \"id\": 212,\n              \"name\": \"asObject\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 213,\n                  \"name\": \"asObject\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Get the dialog object for use with bot.replyWithDialog()\"\n                  },\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"any\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_dialog.ts\",\n                  \"line\": 220,\n                  \"character\": 19\n                }\n              ]\n            },\n            {\n              \"id\": 210,\n              \"name\": \"asString\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 211,\n                  \"name\": \"asString\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Get the dialog object as a JSON encoded string.\"\n                  },\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"string\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_dialog.ts\",\n                  \"line\": 213,\n                  \"character\": 19\n                }\n              ]\n            },\n            {\n              \"id\": 156,\n              \"name\": \"callback_id\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 157,\n                  \"name\": \"callback_id\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Set the dialog's callback_id\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 158,\n                      \"name\": \"v\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"Value for the callback_id\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 140,\n                    \"name\": \"SlackDialog\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_dialog.ts\",\n                  \"line\": 72,\n                  \"character\": 22\n                }\n              ]\n            },\n            {\n              \"id\": 150,\n              \"name\": \"notifyOnCancel\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 151,\n                  \"name\": \"notifyOnCancel\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Set true to have Slack notify you with a `dialog_cancellation` event if a user cancels the dialog without submitting\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 152,\n                      \"name\": \"set\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"True or False\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"boolean\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 140,\n                    \"name\": \"SlackDialog\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_dialog.ts\",\n                  \"line\": 54,\n                  \"character\": 25\n                }\n              ]\n            },\n            {\n              \"id\": 147,\n              \"name\": \"state\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 148,\n                  \"name\": \"state\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Set the dialog's state field\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 149,\n                      \"name\": \"v\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"value for state\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 140,\n                    \"name\": \"SlackDialog\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_dialog.ts\",\n                  \"line\": 45,\n                  \"character\": 16\n                }\n              ]\n            },\n            {\n              \"id\": 159,\n              \"name\": \"submit_label\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 160,\n                  \"name\": \"submit_label\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Set the button text for the submit button on the dialog\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 161,\n                      \"name\": \"v\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"Value for the button label\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 140,\n                    \"name\": \"SlackDialog\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_dialog.ts\",\n                  \"line\": 81,\n                  \"character\": 23\n                }\n              ]\n            },\n            {\n              \"id\": 153,\n              \"name\": \"title\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 154,\n                  \"name\": \"title\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Set the title of the dialog\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 155,\n                      \"name\": \"v\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"Value for title\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 140,\n                    \"name\": \"SlackDialog\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_dialog.ts\",\n                  \"line\": 63,\n                  \"character\": 16\n                }\n              ]\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Constructors\",\n              \"kind\": 512,\n              \"children\": [\n                141\n              ]\n            },\n            {\n              \"title\": \"Methods\",\n              \"kind\": 2048,\n              \"children\": [\n                169,\n                175,\n                200,\n                181,\n                162,\n                193,\n                187,\n                212,\n                210,\n                156,\n                150,\n                147,\n                159,\n                153\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"slack_dialog.ts\",\n              \"line\": 20,\n              \"character\": 24\n            }\n          ],\n          \"props\": [],\n          \"methods\": [\n            {\n              \"id\": 169,\n              \"name\": \"addEmail\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 170,\n                  \"name\": \"addEmail\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Add an email input to the dialog\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 171,\n                      \"name\": \"label\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 172,\n                      \"name\": \"name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 173,\n                      \"name\": \"value\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 174,\n                      \"name\": \"options\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 140,\n                    \"name\": \"SlackDialog\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_dialog.ts\",\n                  \"line\": 120,\n                  \"character\": 19\n                }\n              ]\n            },\n            {\n              \"id\": 175,\n              \"name\": \"addNumber\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 176,\n                  \"name\": \"addNumber\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Add a number input to the dialog\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 177,\n                      \"name\": \"label\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 178,\n                      \"name\": \"name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 179,\n                      \"name\": \"value\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 180,\n                      \"name\": \"options\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 140,\n                    \"name\": \"SlackDialog\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_dialog.ts\",\n                  \"line\": 131,\n                  \"character\": 20\n                }\n              ]\n            },\n            {\n              \"id\": 200,\n              \"name\": \"addSelect\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 201,\n                  \"name\": \"addSelect\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Add a dropdown select input to the dialog\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 202,\n                      \"name\": \"label\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 203,\n                      \"name\": \"name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 204,\n                      \"name\": \"value\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"number\"\n                          },\n                          {\n                            \"type\": \"reference\",\n                            \"typeArguments\": [\n                              {\n                                \"type\": \"intrinsic\",\n                                \"name\": \"string\"\n                              },\n                              {\n                                \"type\": \"intrinsic\",\n                                \"name\": \"any\"\n                              }\n                            ],\n                            \"name\": \"Record\"\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"null\"\n                          }\n                        ]\n                      }\n                    },\n                    {\n                      \"id\": 205,\n                      \"name\": \"option_list\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"reflection\",\n                          \"declaration\": {\n                            \"id\": 206,\n                            \"name\": \"__type\",\n                            \"kind\": 65536,\n                            \"kindString\": \"Type literal\",\n                            \"flags\": {\n                              \"isExported\": true\n                            },\n                            \"children\": [\n                              {\n                                \"id\": 207,\n                                \"name\": \"label\",\n                                \"kind\": 32,\n                                \"kindString\": \"Variable\",\n                                \"flags\": {\n                                  \"isExported\": true,\n                                  \"isExternal\": true\n                                },\n                                \"sources\": [\n                                  {\n                                    \"fileName\": \"slack_dialog.ts\",\n                                    \"line\": 192,\n                                    \"character\": 123\n                                  }\n                                ],\n                                \"type\": {\n                                  \"type\": \"intrinsic\",\n                                  \"name\": \"string\"\n                                }\n                              },\n                              {\n                                \"id\": 208,\n                                \"name\": \"value\",\n                                \"kind\": 32,\n                                \"kindString\": \"Variable\",\n                                \"flags\": {\n                                  \"isExported\": true,\n                                  \"isExternal\": true\n                                },\n                                \"sources\": [\n                                  {\n                                    \"fileName\": \"slack_dialog.ts\",\n                                    \"line\": 192,\n                                    \"character\": 138\n                                  }\n                                ],\n                                \"type\": {\n                                  \"type\": \"union\",\n                                  \"types\": [\n                                    {\n                                      \"type\": \"intrinsic\",\n                                      \"name\": \"string\"\n                                    },\n                                    {\n                                      \"type\": \"intrinsic\",\n                                      \"name\": \"number\"\n                                    },\n                                    {\n                                      \"type\": \"reference\",\n                                      \"typeArguments\": [\n                                        {\n                                          \"type\": \"intrinsic\",\n                                          \"name\": \"string\"\n                                        },\n                                        {\n                                          \"type\": \"intrinsic\",\n                                          \"name\": \"any\"\n                                        }\n                                      ],\n                                      \"name\": \"Record\"\n                                    },\n                                    {\n                                      \"type\": \"intrinsic\",\n                                      \"name\": \"null\"\n                                    }\n                                  ]\n                                }\n                              }\n                            ],\n                            \"groups\": [\n                              {\n                                \"title\": \"Variables\",\n                                \"kind\": 32,\n                                \"children\": [\n                                  207,\n                                  208\n                                ]\n                              }\n                            ],\n                            \"sources\": [\n                              {\n                                \"fileName\": \"slack_dialog.ts\",\n                                \"line\": 192,\n                                \"character\": 115\n                              }\n                            ]\n                          }\n                        }\n                      }\n                    },\n                    {\n                      \"id\": 209,\n                      \"name\": \"options\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 140,\n                    \"name\": \"SlackDialog\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_dialog.ts\",\n                  \"line\": 192,\n                  \"character\": 20\n                }\n              ]\n            },\n            {\n              \"id\": 181,\n              \"name\": \"addTel\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 182,\n                  \"name\": \"addTel\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Add a telephone number input to the dialog\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 183,\n                      \"name\": \"label\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 184,\n                      \"name\": \"name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 185,\n                      \"name\": \"value\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 186,\n                      \"name\": \"options\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 140,\n                    \"name\": \"SlackDialog\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_dialog.ts\",\n                  \"line\": 142,\n                  \"character\": 17\n                }\n              ]\n            },\n            {\n              \"id\": 162,\n              \"name\": \"addText\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 163,\n                  \"name\": \"addText\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Add a text input to the dialog\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 164,\n                      \"name\": \"label\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"any\"\n                          }\n                        ]\n                      }\n                    },\n                    {\n                      \"id\": 165,\n                      \"name\": \"name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 166,\n                      \"name\": \"value\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 167,\n                      \"name\": \"options\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"union\",\n                        \"types\": [\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          },\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"any\"\n                          }\n                        ]\n                      }\n                    },\n                    {\n                      \"id\": 168,\n                      \"name\": \"subtype\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 140,\n                    \"name\": \"SlackDialog\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_dialog.ts\",\n                  \"line\": 94,\n                  \"character\": 18\n                }\n              ]\n            },\n            {\n              \"id\": 193,\n              \"name\": \"addTextarea\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 194,\n                  \"name\": \"addTextarea\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Add a text area input to the dialog\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 195,\n                      \"name\": \"label\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 196,\n                      \"name\": \"name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 197,\n                      \"name\": \"value\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 198,\n                      \"name\": \"options\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 199,\n                      \"name\": \"subtype\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 140,\n                    \"name\": \"SlackDialog\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_dialog.ts\",\n                  \"line\": 165,\n                  \"character\": 22\n                }\n              ]\n            },\n            {\n              \"id\": 187,\n              \"name\": \"addUrl\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 188,\n                  \"name\": \"addUrl\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Add a URL input to the dialog\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 189,\n                      \"name\": \"label\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 190,\n                      \"name\": \"name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 191,\n                      \"name\": \"value\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 192,\n                      \"name\": \"options\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 140,\n                    \"name\": \"SlackDialog\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_dialog.ts\",\n                  \"line\": 153,\n                  \"character\": 17\n                }\n              ]\n            },\n            {\n              \"id\": 212,\n              \"name\": \"asObject\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 213,\n                  \"name\": \"asObject\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Get the dialog object for use with bot.replyWithDialog()\"\n                  },\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"any\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_dialog.ts\",\n                  \"line\": 220,\n                  \"character\": 19\n                }\n              ]\n            },\n            {\n              \"id\": 210,\n              \"name\": \"asString\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 211,\n                  \"name\": \"asString\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Get the dialog object as a JSON encoded string.\"\n                  },\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"string\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_dialog.ts\",\n                  \"line\": 213,\n                  \"character\": 19\n                }\n              ]\n            },\n            {\n              \"id\": 156,\n              \"name\": \"callback_id\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 157,\n                  \"name\": \"callback_id\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Set the dialog's callback_id\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 158,\n                      \"name\": \"v\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"Value for the callback_id\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 140,\n                    \"name\": \"SlackDialog\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_dialog.ts\",\n                  \"line\": 72,\n                  \"character\": 22\n                }\n              ]\n            },\n            {\n              \"id\": 150,\n              \"name\": \"notifyOnCancel\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 151,\n                  \"name\": \"notifyOnCancel\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Set true to have Slack notify you with a `dialog_cancellation` event if a user cancels the dialog without submitting\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 152,\n                      \"name\": \"set\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"True or False\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"boolean\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 140,\n                    \"name\": \"SlackDialog\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_dialog.ts\",\n                  \"line\": 54,\n                  \"character\": 25\n                }\n              ]\n            },\n            {\n              \"id\": 147,\n              \"name\": \"state\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 148,\n                  \"name\": \"state\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Set the dialog's state field\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 149,\n                      \"name\": \"v\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"value for state\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 140,\n                    \"name\": \"SlackDialog\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_dialog.ts\",\n                  \"line\": 45,\n                  \"character\": 16\n                }\n              ]\n            },\n            {\n              \"id\": 159,\n              \"name\": \"submit_label\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 160,\n                  \"name\": \"submit_label\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Set the button text for the submit button on the dialog\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 161,\n                      \"name\": \"v\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"Value for the button label\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 140,\n                    \"name\": \"SlackDialog\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_dialog.ts\",\n                  \"line\": 81,\n                  \"character\": 23\n                }\n              ]\n            },\n            {\n              \"id\": 153,\n              \"name\": \"title\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 154,\n                  \"name\": \"title\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Set the title of the dialog\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 155,\n                      \"name\": \"v\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"Value for title\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 140,\n                    \"name\": \"SlackDialog\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_dialog.ts\",\n                  \"line\": 63,\n                  \"character\": 16\n                }\n              ]\n            }\n          ],\n          \"constructors\": [\n            {\n              \"id\": 141,\n              \"name\": \"constructor\",\n              \"kind\": 512,\n              \"kindString\": \"Constructor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Create a new dialog object\"\n              },\n              \"signatures\": [\n                {\n                  \"id\": 142,\n                  \"name\": \"new SlackDialog\",\n                  \"kind\": 16384,\n                  \"kindString\": \"Constructor signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Create a new dialog object\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 143,\n                      \"name\": \"title\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"Title of dialog\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 144,\n                      \"name\": \"callback_id\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"Callback id of dialog\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 145,\n                      \"name\": \"submit_label\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"Label for the submit button\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 146,\n                      \"name\": \"elements\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"An array of dialog elements\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 140,\n                    \"name\": \"SlackDialog\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_dialog.ts\",\n                  \"line\": 21,\n                  \"character\": 22\n                }\n              ]\n            }\n          ]\n        },\n        {\n          \"id\": 223,\n          \"name\": \"SlackEventMiddleware\",\n          \"kind\": 128,\n          \"kindString\": \"Class\",\n          \"flags\": {\n            \"isExported\": true,\n            \"isExternal\": true\n          },\n          \"comment\": {\n            \"shortText\": \"A middleware for Botkit developers using the BotBuilder SlackAdapter class.\\nThis middleware causes Botkit to emit message events by their `type` or `subtype` field rather than their default BotBuilder Activity type (limited to message or event).\\nThis keeps the new Botkit behavior consistent withprevious versions, and provides helpful filtering on the many event types that Slack sends.\\nTo use this, bind it to the adapter before creating the Botkit controller:\\n```javascript\\nconst adapter = new SlackAdapter(options);\\nadapter.use(new SlackEventMiddleware());\\nconst controller = new Botkit({\\n     adapter: adapter,\\n     // ...\\n});\",\n            \"text\": \"// can bind directly to channel_join (which starts as a message with type message and subtype channel_join)\\ncontroller.on('channel_join', async(bot, message) => {\\n // send a welcome\\n});\\n```\\n\"\n          },\n          \"children\": [\n            {\n              \"id\": 224,\n              \"name\": \"onTurn\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 225,\n                  \"name\": \"onTurn\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Not for direct use - implements the MiddlewareSet's required onTurn function used to process the event\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 226,\n                      \"name\": \"context\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"TurnContext\"\n                      }\n                    },\n                    {\n                      \"id\": 227,\n                      \"name\": \"next\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 228,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 229,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"any\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"slackevent_middleware.ts\",\n                              \"line\": 36,\n                              \"character\": 51\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slackevent_middleware.ts\",\n                  \"line\": 36,\n                  \"character\": 23\n                }\n              ]\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Methods\",\n              \"kind\": 2048,\n              \"children\": [\n                224\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"slackevent_middleware.ts\",\n              \"line\": 30,\n              \"character\": 33\n            }\n          ],\n          \"extendedTypes\": [\n            {\n              \"type\": \"intrinsic\",\n              \"name\": \"any\"\n            }\n          ],\n          \"props\": [],\n          \"methods\": [\n            {\n              \"id\": 224,\n              \"name\": \"onTurn\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 225,\n                  \"name\": \"onTurn\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Not for direct use - implements the MiddlewareSet's required onTurn function used to process the event\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 226,\n                      \"name\": \"context\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"TurnContext\"\n                      }\n                    },\n                    {\n                      \"id\": 227,\n                      \"name\": \"next\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 228,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 229,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"any\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"slackevent_middleware.ts\",\n                              \"line\": 36,\n                              \"character\": 51\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"slackevent_middleware.ts\",\n                  \"line\": 36,\n                  \"character\": 23\n                }\n              ]\n            }\n          ],\n          \"constructors\": []\n        },\n        {\n          \"id\": 215,\n          \"name\": \"SlackMessageTypeMiddleware\",\n          \"kind\": 128,\n          \"kindString\": \"Class\",\n          \"flags\": {\n            \"isExported\": true,\n            \"isExternal\": true\n          },\n          \"comment\": {\n            \"shortText\": \"A middleware for Botkit developers using the BotBuilder SlackAdapter class.\\nThis middleware causes Botkit to emit more specialized events for the different types of message that Slack might send.\\nResponsible for classifying messages:\",\n            \"text\": \"     * `direct_message` events are messages received through 1:1 direct messages with the bot\\n     * `direct_mention` events are messages that start with a mention of the bot, i.e \\\"@mybot hello there\\\"\\n     * `mention` events are messages that include a mention of the bot, but not at the start, i.e \\\"hello there @mybot\\\"\\n\\nIn addition, messages from bots and changing them to `bot_message` events. All other types of message encountered remain `message` events.\\n\\nTo use this, bind it to the adapter before creating the Botkit controller:\\n```javascript\\nconst adapter = new SlackAdapter(options);\\nadapter.use(new SlackMessageTypeMiddleware());\\nconst controller = new Botkit({\\n     adapter: adapter,\\n     // ...\\n});\\n```\\n\"\n          },\n          \"children\": [\n            {\n              \"id\": 216,\n              \"name\": \"onTurn\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 217,\n                  \"name\": \"onTurn\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Not for direct use - implements the MiddlewareSet's required onTurn function used to process the event\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 218,\n                      \"name\": \"context\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"TurnContext\"\n                      }\n                    },\n                    {\n                      \"id\": 219,\n                      \"name\": \"next\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 220,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 221,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"any\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"messagetype_middleware.ts\",\n                              \"line\": 39,\n                              \"character\": 51\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"messagetype_middleware.ts\",\n                  \"line\": 39,\n                  \"character\": 23\n                }\n              ]\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Methods\",\n              \"kind\": 2048,\n              \"children\": [\n                216\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"messagetype_middleware.ts\",\n              \"line\": 33,\n              \"character\": 39\n            }\n          ],\n          \"extendedTypes\": [\n            {\n              \"type\": \"intrinsic\",\n              \"name\": \"any\"\n            }\n          ],\n          \"props\": [],\n          \"methods\": [\n            {\n              \"id\": 216,\n              \"name\": \"onTurn\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 217,\n                  \"name\": \"onTurn\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Not for direct use - implements the MiddlewareSet's required onTurn function used to process the event\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 218,\n                      \"name\": \"context\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {},\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"TurnContext\"\n                      }\n                    },\n                    {\n                      \"id\": 219,\n                      \"name\": \"next\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 220,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 221,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"any\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"messagetype_middleware.ts\",\n                              \"line\": 39,\n                              \"character\": 51\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"messagetype_middleware.ts\",\n                  \"line\": 39,\n                  \"character\": 23\n                }\n              ]\n            }\n          ],\n          \"constructors\": []\n        }\n      ],\n      \"interfaces\": [\n        {\n          \"id\": 132,\n          \"name\": \"AuthTestResult\",\n          \"kind\": 256,\n          \"kindString\": \"Interface\",\n          \"flags\": {\n            \"isExternal\": true\n          },\n          \"children\": [\n            {\n              \"id\": 137,\n              \"name\": \"ok\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 797,\n                  \"character\": 6\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"boolean\"\n              }\n            },\n            {\n              \"id\": 134,\n              \"name\": \"team\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 794,\n                  \"character\": 8\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 135,\n              \"name\": \"team_id\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 795,\n                  \"character\": 11\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 133,\n              \"name\": \"user\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 793,\n                  \"character\": 8\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 136,\n              \"name\": \"user_id\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 796,\n                  \"character\": 11\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Properties\",\n              \"kind\": 1024,\n              \"children\": [\n                137,\n                134,\n                135,\n                133,\n                136\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"slack_adapter.ts\",\n              \"line\": 792,\n              \"character\": 24\n            }\n          ],\n          \"extendedTypes\": [\n            {\n              \"type\": \"intrinsic\",\n              \"name\": \"any\"\n            }\n          ],\n          \"props\": [\n            {\n              \"id\": 137,\n              \"name\": \"ok\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 797,\n                  \"character\": 6\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"boolean\"\n              }\n            },\n            {\n              \"id\": 134,\n              \"name\": \"team\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 794,\n                  \"character\": 8\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 135,\n              \"name\": \"team_id\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 795,\n                  \"character\": 11\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 133,\n              \"name\": \"user\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 793,\n                  \"character\": 8\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 136,\n              \"name\": \"user_id\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 796,\n                  \"character\": 11\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            }\n          ]\n        },\n        {\n          \"id\": 126,\n          \"name\": \"ChatPostMessageResult\",\n          \"kind\": 256,\n          \"kindString\": \"Interface\",\n          \"flags\": {\n            \"isExternal\": true\n          },\n          \"children\": [\n            {\n              \"id\": 127,\n              \"name\": \"channel\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 783,\n                  \"character\": 11\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 129,\n              \"name\": \"message\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 785,\n                  \"character\": 11\n                }\n              ],\n              \"type\": {\n                \"type\": \"reflection\",\n                \"declaration\": {\n                  \"id\": 130,\n                  \"name\": \"__type\",\n                  \"kind\": 65536,\n                  \"kindString\": \"Type literal\",\n                  \"flags\": {},\n                  \"children\": [\n                    {\n                      \"id\": 131,\n                      \"name\": \"text\",\n                      \"kind\": 32,\n                      \"kindString\": \"Variable\",\n                      \"flags\": {\n                        \"isExternal\": true\n                      },\n                      \"sources\": [\n                        {\n                          \"fileName\": \"slack_adapter.ts\",\n                          \"line\": 786,\n                          \"character\": 12\n                        }\n                      ],\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"groups\": [\n                    {\n                      \"title\": \"Variables\",\n                      \"kind\": 32,\n                      \"children\": [\n                        131\n                      ]\n                    }\n                  ],\n                  \"sources\": [\n                    {\n                      \"fileName\": \"slack_adapter.ts\",\n                      \"line\": 785,\n                      \"character\": 12\n                    }\n                  ]\n                }\n              }\n            },\n            {\n              \"id\": 128,\n              \"name\": \"ts\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 784,\n                  \"character\": 6\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Properties\",\n              \"kind\": 1024,\n              \"children\": [\n                127,\n                129,\n                128\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"slack_adapter.ts\",\n              \"line\": 782,\n              \"character\": 31\n            }\n          ],\n          \"extendedTypes\": [\n            {\n              \"type\": \"intrinsic\",\n              \"name\": \"any\"\n            }\n          ],\n          \"props\": [\n            {\n              \"id\": 127,\n              \"name\": \"channel\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 783,\n                  \"character\": 11\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 129,\n              \"name\": \"message\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 785,\n                  \"character\": 11\n                }\n              ],\n              \"type\": {\n                \"type\": \"reflection\",\n                \"declaration\": {\n                  \"id\": 130,\n                  \"name\": \"__type\",\n                  \"kind\": 65536,\n                  \"kindString\": \"Type literal\",\n                  \"flags\": {},\n                  \"children\": [\n                    {\n                      \"id\": 131,\n                      \"name\": \"text\",\n                      \"kind\": 32,\n                      \"kindString\": \"Variable\",\n                      \"flags\": {\n                        \"isExternal\": true\n                      },\n                      \"sources\": [\n                        {\n                          \"fileName\": \"slack_adapter.ts\",\n                          \"line\": 786,\n                          \"character\": 12\n                        }\n                      ],\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"groups\": [\n                    {\n                      \"title\": \"Variables\",\n                      \"kind\": 32,\n                      \"children\": [\n                        131\n                      ]\n                    }\n                  ],\n                  \"sources\": [\n                    {\n                      \"fileName\": \"slack_adapter.ts\",\n                      \"line\": 785,\n                      \"character\": 12\n                    }\n                  ]\n                }\n              }\n            },\n            {\n              \"id\": 128,\n              \"name\": \"ts\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 784,\n                  \"character\": 6\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            }\n          ]\n        },\n        {\n          \"id\": 108,\n          \"name\": \"SlackAdapterOptions\",\n          \"kind\": 256,\n          \"kindString\": \"Interface\",\n          \"flags\": {\n            \"isExported\": true,\n            \"isExternal\": true\n          },\n          \"comment\": {\n            \"shortText\": \"This interface defines the options that can be passed into the SlackAdapter constructor function.\"\n          },\n          \"children\": [\n            {\n              \"id\": 111,\n              \"name\": \"botToken\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A token (provided by Slack) for a bot to work on a single workspace\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 739,\n                  \"character\": 12\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 112,\n              \"name\": \"clientId\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"The oauth client id provided by Slack for multi-team apps\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 744,\n                  \"character\": 12\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 113,\n              \"name\": \"clientSecret\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"The oauth client secret provided by Slack for multi-team apps\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 748,\n                  \"character\": 16\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 110,\n              \"name\": \"clientSigningSecret\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A token used to validate that incoming webhooks originated with Slack.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 735,\n                  \"character\": 23\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 125,\n              \"name\": \"enable_incomplete\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Allow the adapter to startup without a complete configuration.\\nThis is risky as it may result in a non-functioning or insecure adapter.\\nThis should only be used when getting started.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 777,\n                  \"character\": 21\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"boolean\"\n              }\n            },\n            {\n              \"id\": 121,\n              \"name\": \"getBotUserByTeam\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A method that receives a Slack team id and returns the bot user id associated with that team. Required for multi-team apps.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 770,\n                  \"character\": 20\n                }\n              ],\n              \"type\": {\n                \"type\": \"reflection\",\n                \"declaration\": {\n                  \"id\": 122,\n                  \"name\": \"__type\",\n                  \"kind\": 65536,\n                  \"kindString\": \"Type literal\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"signatures\": [\n                    {\n                      \"id\": 123,\n                      \"name\": \"__call\",\n                      \"kind\": 4096,\n                      \"kindString\": \"Call signature\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"parameters\": [\n                        {\n                          \"id\": 124,\n                          \"name\": \"teamId\",\n                          \"kind\": 32768,\n                          \"kindString\": \"Parameter\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"type\": {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        }\n                      ],\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        ],\n                        \"name\": \"Promise\"\n                      }\n                    }\n                  ],\n                  \"sources\": [\n                    {\n                      \"fileName\": \"slack_adapter.ts\",\n                      \"line\": 770,\n                      \"character\": 22\n                    }\n                  ]\n                }\n              }\n            },\n            {\n              \"id\": 117,\n              \"name\": \"getTokenForTeam\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A method that receives a Slack team id and returns the bot token associated with that team. Required for multi-team apps.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 765,\n                  \"character\": 19\n                }\n              ],\n              \"type\": {\n                \"type\": \"reflection\",\n                \"declaration\": {\n                  \"id\": 118,\n                  \"name\": \"__type\",\n                  \"kind\": 65536,\n                  \"kindString\": \"Type literal\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"signatures\": [\n                    {\n                      \"id\": 119,\n                      \"name\": \"__call\",\n                      \"kind\": 4096,\n                      \"kindString\": \"Call signature\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"parameters\": [\n                        {\n                          \"id\": 120,\n                          \"name\": \"teamId\",\n                          \"kind\": 32768,\n                          \"kindString\": \"Parameter\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"type\": {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        }\n                      ],\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        ],\n                        \"name\": \"Promise\"\n                      }\n                    }\n                  ],\n                  \"sources\": [\n                    {\n                      \"fileName\": \"slack_adapter.ts\",\n                      \"line\": 765,\n                      \"character\": 21\n                    }\n                  ]\n                }\n              }\n            },\n            {\n              \"id\": 115,\n              \"name\": \"oauthVersion\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Which version of Slack's oauth protocol to use, v1 or v2. Defaults to v1.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 756,\n                  \"character\": 16\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 116,\n              \"name\": \"redirectUri\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"The URL users will be redirected to after an oauth flow. In most cases, should be `https://<mydomain.com>/install/auth`\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 760,\n                  \"character\": 15\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 114,\n              \"name\": \"scopes\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A array of scope names that are being requested during the oauth process. Must match the scopes defined at api.slack.com\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 752,\n                  \"character\": 10\n                }\n              ],\n              \"type\": {\n                \"type\": \"array\",\n                \"elementType\": {\n                  \"type\": \"intrinsic\",\n                  \"name\": \"string\"\n                }\n              }\n            },\n            {\n              \"id\": 109,\n              \"name\": \"verificationToken\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Legacy method for validating the origin of incoming webhooks. Prefer `clientSigningSecret` instead.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 731,\n                  \"character\": 21\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Properties\",\n              \"kind\": 1024,\n              \"children\": [\n                111,\n                112,\n                113,\n                110,\n                125,\n                121,\n                117,\n                115,\n                116,\n                114,\n                109\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"slack_adapter.ts\",\n              \"line\": 727,\n              \"character\": 36\n            }\n          ],\n          \"props\": [\n            {\n              \"id\": 111,\n              \"name\": \"botToken\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A token (provided by Slack) for a bot to work on a single workspace\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 739,\n                  \"character\": 12\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 112,\n              \"name\": \"clientId\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"The oauth client id provided by Slack for multi-team apps\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 744,\n                  \"character\": 12\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 113,\n              \"name\": \"clientSecret\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"The oauth client secret provided by Slack for multi-team apps\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 748,\n                  \"character\": 16\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 110,\n              \"name\": \"clientSigningSecret\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A token used to validate that incoming webhooks originated with Slack.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 735,\n                  \"character\": 23\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 125,\n              \"name\": \"enable_incomplete\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Allow the adapter to startup without a complete configuration.\\nThis is risky as it may result in a non-functioning or insecure adapter.\\nThis should only be used when getting started.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 777,\n                  \"character\": 21\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"boolean\"\n              }\n            },\n            {\n              \"id\": 121,\n              \"name\": \"getBotUserByTeam\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A method that receives a Slack team id and returns the bot user id associated with that team. Required for multi-team apps.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 770,\n                  \"character\": 20\n                }\n              ],\n              \"type\": {\n                \"type\": \"reflection\",\n                \"declaration\": {\n                  \"id\": 122,\n                  \"name\": \"__type\",\n                  \"kind\": 65536,\n                  \"kindString\": \"Type literal\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"signatures\": [\n                    {\n                      \"id\": 123,\n                      \"name\": \"__call\",\n                      \"kind\": 4096,\n                      \"kindString\": \"Call signature\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"parameters\": [\n                        {\n                          \"id\": 124,\n                          \"name\": \"teamId\",\n                          \"kind\": 32768,\n                          \"kindString\": \"Parameter\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"type\": {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        }\n                      ],\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        ],\n                        \"name\": \"Promise\"\n                      }\n                    }\n                  ],\n                  \"sources\": [\n                    {\n                      \"fileName\": \"slack_adapter.ts\",\n                      \"line\": 770,\n                      \"character\": 22\n                    }\n                  ]\n                }\n              }\n            },\n            {\n              \"id\": 117,\n              \"name\": \"getTokenForTeam\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A method that receives a Slack team id and returns the bot token associated with that team. Required for multi-team apps.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 765,\n                  \"character\": 19\n                }\n              ],\n              \"type\": {\n                \"type\": \"reflection\",\n                \"declaration\": {\n                  \"id\": 118,\n                  \"name\": \"__type\",\n                  \"kind\": 65536,\n                  \"kindString\": \"Type literal\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"signatures\": [\n                    {\n                      \"id\": 119,\n                      \"name\": \"__call\",\n                      \"kind\": 4096,\n                      \"kindString\": \"Call signature\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"parameters\": [\n                        {\n                          \"id\": 120,\n                          \"name\": \"teamId\",\n                          \"kind\": 32768,\n                          \"kindString\": \"Parameter\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"type\": {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        }\n                      ],\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        ],\n                        \"name\": \"Promise\"\n                      }\n                    }\n                  ],\n                  \"sources\": [\n                    {\n                      \"fileName\": \"slack_adapter.ts\",\n                      \"line\": 765,\n                      \"character\": 21\n                    }\n                  ]\n                }\n              }\n            },\n            {\n              \"id\": 115,\n              \"name\": \"oauthVersion\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Which version of Slack's oauth protocol to use, v1 or v2. Defaults to v1.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 756,\n                  \"character\": 16\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 116,\n              \"name\": \"redirectUri\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"The URL users will be redirected to after an oauth flow. In most cases, should be `https://<mydomain.com>/install/auth`\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 760,\n                  \"character\": 15\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 114,\n              \"name\": \"scopes\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A array of scope names that are being requested during the oauth process. Must match the scopes defined at api.slack.com\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 752,\n                  \"character\": 10\n                }\n              ],\n              \"type\": {\n                \"type\": \"array\",\n                \"elementType\": {\n                  \"type\": \"intrinsic\",\n                  \"name\": \"string\"\n                }\n              }\n            },\n            {\n              \"id\": 109,\n              \"name\": \"verificationToken\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Legacy method for validating the origin of incoming webhooks. Prefer `clientSigningSecret` instead.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"slack_adapter.ts\",\n                  \"line\": 731,\n                  \"character\": 21\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            }\n          ]\n        }\n      ]\n    },\n    {\n      \"name\": \"Botkit for Hangouts\",\n      \"packageName\": \"botbuilder-adapter-hangouts\",\n      \"path\": \"reference/hangouts.md\",\n      \"classes\": [\n        {\n          \"id\": 28,\n          \"name\": \"HangoutsAdapter\",\n          \"kind\": 128,\n          \"kindString\": \"Class\",\n          \"flags\": {\n            \"isExported\": true,\n            \"isExternal\": true\n          },\n          \"comment\": {\n            \"shortText\": \"Connect [Botkit](https://www.npmjs.com/package/botkit) or [BotBuilder](https://www.npmjs.com/package/botbuilder) to Google Hangouts\"\n          },\n          \"children\": [\n            {\n              \"id\": 32,\n              \"name\": \"constructor\",\n              \"kind\": 512,\n              \"kindString\": \"Constructor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Create an adapter to handle incoming messages from Google Hangouts and translate them into a standard format for processing by your bot.\",\n                \"text\": \"Use with Botkit:\\n```javascript\\nconst adapter = new HangoutsAdapter({\\n     token: process.env.GOOGLE_TOKEN,\\n     google_auth_params: {\\n         credentials: process.env.GOOGLE_CREDS\\n     }\\n});\\nconst controller = new Botkit({\\n     adapter: adapter,\\n     // ... other configuration options\\n});\\n```\\n\\nUse with BotBuilder:\\n```javascript\\nconst adapter = new HangoutsAdapter({\\n     token: process.env.GOOGLE_TOKEN,\\n     google_auth_params: {\\n         credentials: process.env.GOOGLE_CREDS\\n     }\\n});\\n// set up restify...\\nconst server = restify.createServer();\\nserver.use(restify.plugins.bodyParser());\\nserver.post('/api/messages', (req, res) => {\\n     adapter.processActivity(req, res, async(context) => {\\n         // do your bot logic here!\\n     });\\n});\\n```\\n\"\n              },\n              \"signatures\": [\n                {\n                  \"id\": 33,\n                  \"name\": \"new HangoutsAdapter\",\n                  \"kind\": 16384,\n                  \"kindString\": \"Constructor signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Create an adapter to handle incoming messages from Google Hangouts and translate them into a standard format for processing by your bot.\",\n                    \"text\": \"Use with Botkit:\\n```javascript\\nconst adapter = new HangoutsAdapter({\\n     token: process.env.GOOGLE_TOKEN,\\n     google_auth_params: {\\n         credentials: process.env.GOOGLE_CREDS\\n     }\\n});\\nconst controller = new Botkit({\\n     adapter: adapter,\\n     // ... other configuration options\\n});\\n```\\n\\nUse with BotBuilder:\\n```javascript\\nconst adapter = new HangoutsAdapter({\\n     token: process.env.GOOGLE_TOKEN,\\n     google_auth_params: {\\n         credentials: process.env.GOOGLE_CREDS\\n     }\\n});\\n// set up restify...\\nconst server = restify.createServer();\\nserver.use(restify.plugins.bodyParser());\\nserver.post('/api/messages', (req, res) => {\\n     adapter.processActivity(req, res, async(context) => {\\n         // do your bot logic here!\\n     });\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 34,\n                      \"name\": \"options\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"An object containing API credentials and a webhook verification token\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 62,\n                        \"name\": \"HangoutsAdapterOptions\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 28,\n                    \"name\": \"HangoutsAdapter\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"hangouts_adapter.ts\",\n                  \"line\": 46,\n                  \"character\": 21\n                }\n              ]\n            },\n            {\n              \"id\": 47,\n              \"name\": \"continueConversation\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 48,\n                  \"name\": \"continueConversation\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Standard BotBuilder adapter method for continuing an existing conversation based on a conversation reference.\\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#continueconversation)\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 49,\n                      \"name\": \"reference\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A conversation reference to be applied to future messages.\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"ConversationReference\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    },\n                    {\n                      \"id\": 50,\n                      \"name\": \"logic\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A bot logic function that will perform continuing action in the form `async(context) => { ... }`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 51,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 52,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 53,\n                                  \"name\": \"context\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"name\": \"TurnContext\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"void\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"hangouts_adapter.ts\",\n                              \"line\": 267,\n                              \"character\": 87\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"hangouts_adapter.ts\",\n                  \"line\": 267,\n                  \"character\": 37\n                }\n              ]\n            },\n            {\n              \"id\": 43,\n              \"name\": \"deleteActivity\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 44,\n                  \"name\": \"deleteActivity\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Standard BotBuilder adapter method to delete a previous message.\\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#deleteactivity).\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 45,\n                      \"name\": \"context\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A TurnContext representing the current incoming message and environment. (Not used)\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"TurnContext\"\n                      }\n                    },\n                    {\n                      \"id\": 46,\n                      \"name\": \"reference\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An object in the form `{activityId: <id of message to delete>}`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"ConversationReference\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"hangouts_adapter.ts\",\n                  \"line\": 243,\n                  \"character\": 31\n                }\n              ]\n            },\n            {\n              \"id\": 54,\n              \"name\": \"processActivity\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 55,\n                  \"name\": \"processActivity\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Accept an incoming webhook request and convert it into a TurnContext which can be processed by the bot's logic.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 56,\n                      \"name\": \"req\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A request object from Restify or Express\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 57,\n                      \"name\": \"res\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A response object from Restify or Express\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 58,\n                      \"name\": \"logic\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A bot logic function in the form `async(context) => { ... }`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 59,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 60,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 61,\n                                  \"name\": \"context\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"name\": \"TurnContext\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"void\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"hangouts_adapter.ts\",\n                              \"line\": 284,\n                              \"character\": 49\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"hangouts_adapter.ts\",\n                  \"line\": 284,\n                  \"character\": 32\n                }\n              ]\n            },\n            {\n              \"id\": 35,\n              \"name\": \"sendActivities\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 36,\n                  \"name\": \"sendActivities\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Standard BotBuilder adapter method to send a message from the bot to the messaging API.\\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#sendactivities).\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 37,\n                      \"name\": \"context\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A TurnContext representing the current incoming message and environment. (Not used)\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"TurnContext\"\n                      }\n                    },\n                    {\n                      \"id\": 38,\n                      \"name\": \"activities\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An array of outgoing activities to be sent back to the messaging API.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"reference\",\n                          \"typeArguments\": [\n                            {\n                              \"type\": \"reference\",\n                              \"name\": \"Activity\"\n                            }\n                          ],\n                          \"name\": \"Partial\"\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"reference\",\n                          \"name\": \"ResourceResponse\"\n                        }\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"hangouts_adapter.ts\",\n                  \"line\": 185,\n                  \"character\": 31\n                }\n              ]\n            },\n            {\n              \"id\": 39,\n              \"name\": \"updateActivity\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 40,\n                  \"name\": \"updateActivity\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Standard BotBuilder adapter method to update a previous message with new content.\\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#updateactivity).\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 41,\n                      \"name\": \"context\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A TurnContext representing the current incoming message and environment. (Not used)\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"TurnContext\"\n                      }\n                    },\n                    {\n                      \"id\": 42,\n                      \"name\": \"activity\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"The updated activity in the form `{id: <id of activity to update>, text: <updated text>, cards?: [<array of updated hangouts cards>]}`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"Activity\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"hangouts_adapter.ts\",\n                  \"line\": 212,\n                  \"character\": 31\n                }\n              ]\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Constructors\",\n              \"kind\": 512,\n              \"children\": [\n                32\n              ]\n            },\n            {\n              \"title\": \"Methods\",\n              \"kind\": 2048,\n              \"children\": [\n                47,\n                43,\n                54,\n                35,\n                39\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"hangouts_adapter.ts\",\n              \"line\": 21,\n              \"character\": 28\n            }\n          ],\n          \"extendedTypes\": [\n            {\n              \"type\": \"intrinsic\",\n              \"name\": \"any\"\n            }\n          ],\n          \"props\": [],\n          \"methods\": [\n            {\n              \"id\": 47,\n              \"name\": \"continueConversation\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 48,\n                  \"name\": \"continueConversation\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Standard BotBuilder adapter method for continuing an existing conversation based on a conversation reference.\\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#continueconversation)\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 49,\n                      \"name\": \"reference\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A conversation reference to be applied to future messages.\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"ConversationReference\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    },\n                    {\n                      \"id\": 50,\n                      \"name\": \"logic\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A bot logic function that will perform continuing action in the form `async(context) => { ... }`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 51,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 52,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 53,\n                                  \"name\": \"context\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"name\": \"TurnContext\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"void\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"hangouts_adapter.ts\",\n                              \"line\": 267,\n                              \"character\": 87\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"hangouts_adapter.ts\",\n                  \"line\": 267,\n                  \"character\": 37\n                }\n              ]\n            },\n            {\n              \"id\": 43,\n              \"name\": \"deleteActivity\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 44,\n                  \"name\": \"deleteActivity\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Standard BotBuilder adapter method to delete a previous message.\\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#deleteactivity).\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 45,\n                      \"name\": \"context\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A TurnContext representing the current incoming message and environment. (Not used)\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"TurnContext\"\n                      }\n                    },\n                    {\n                      \"id\": 46,\n                      \"name\": \"reference\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An object in the form `{activityId: <id of message to delete>}`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"ConversationReference\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"hangouts_adapter.ts\",\n                  \"line\": 243,\n                  \"character\": 31\n                }\n              ]\n            },\n            {\n              \"id\": 54,\n              \"name\": \"processActivity\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 55,\n                  \"name\": \"processActivity\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Accept an incoming webhook request and convert it into a TurnContext which can be processed by the bot's logic.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 56,\n                      \"name\": \"req\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A request object from Restify or Express\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 57,\n                      \"name\": \"res\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A response object from Restify or Express\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 58,\n                      \"name\": \"logic\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A bot logic function in the form `async(context) => { ... }`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 59,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 60,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 61,\n                                  \"name\": \"context\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"name\": \"TurnContext\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"void\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"hangouts_adapter.ts\",\n                              \"line\": 284,\n                              \"character\": 49\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"hangouts_adapter.ts\",\n                  \"line\": 284,\n                  \"character\": 32\n                }\n              ]\n            },\n            {\n              \"id\": 35,\n              \"name\": \"sendActivities\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 36,\n                  \"name\": \"sendActivities\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Standard BotBuilder adapter method to send a message from the bot to the messaging API.\\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#sendactivities).\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 37,\n                      \"name\": \"context\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A TurnContext representing the current incoming message and environment. (Not used)\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"TurnContext\"\n                      }\n                    },\n                    {\n                      \"id\": 38,\n                      \"name\": \"activities\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An array of outgoing activities to be sent back to the messaging API.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"reference\",\n                          \"typeArguments\": [\n                            {\n                              \"type\": \"reference\",\n                              \"name\": \"Activity\"\n                            }\n                          ],\n                          \"name\": \"Partial\"\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"reference\",\n                          \"name\": \"ResourceResponse\"\n                        }\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"hangouts_adapter.ts\",\n                  \"line\": 185,\n                  \"character\": 31\n                }\n              ]\n            },\n            {\n              \"id\": 39,\n              \"name\": \"updateActivity\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 40,\n                  \"name\": \"updateActivity\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Standard BotBuilder adapter method to update a previous message with new content.\\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#updateactivity).\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 41,\n                      \"name\": \"context\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A TurnContext representing the current incoming message and environment. (Not used)\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"TurnContext\"\n                      }\n                    },\n                    {\n                      \"id\": 42,\n                      \"name\": \"activity\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"The updated activity in the form `{id: <id of activity to update>, text: <updated text>, cards?: [<array of updated hangouts cards>]}`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"Activity\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"hangouts_adapter.ts\",\n                  \"line\": 212,\n                  \"character\": 31\n                }\n              ]\n            }\n          ],\n          \"constructors\": [\n            {\n              \"id\": 32,\n              \"name\": \"constructor\",\n              \"kind\": 512,\n              \"kindString\": \"Constructor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Create an adapter to handle incoming messages from Google Hangouts and translate them into a standard format for processing by your bot.\",\n                \"text\": \"Use with Botkit:\\n```javascript\\nconst adapter = new HangoutsAdapter({\\n     token: process.env.GOOGLE_TOKEN,\\n     google_auth_params: {\\n         credentials: process.env.GOOGLE_CREDS\\n     }\\n});\\nconst controller = new Botkit({\\n     adapter: adapter,\\n     // ... other configuration options\\n});\\n```\\n\\nUse with BotBuilder:\\n```javascript\\nconst adapter = new HangoutsAdapter({\\n     token: process.env.GOOGLE_TOKEN,\\n     google_auth_params: {\\n         credentials: process.env.GOOGLE_CREDS\\n     }\\n});\\n// set up restify...\\nconst server = restify.createServer();\\nserver.use(restify.plugins.bodyParser());\\nserver.post('/api/messages', (req, res) => {\\n     adapter.processActivity(req, res, async(context) => {\\n         // do your bot logic here!\\n     });\\n});\\n```\\n\"\n              },\n              \"signatures\": [\n                {\n                  \"id\": 33,\n                  \"name\": \"new HangoutsAdapter\",\n                  \"kind\": 16384,\n                  \"kindString\": \"Constructor signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Create an adapter to handle incoming messages from Google Hangouts and translate them into a standard format for processing by your bot.\",\n                    \"text\": \"Use with Botkit:\\n```javascript\\nconst adapter = new HangoutsAdapter({\\n     token: process.env.GOOGLE_TOKEN,\\n     google_auth_params: {\\n         credentials: process.env.GOOGLE_CREDS\\n     }\\n});\\nconst controller = new Botkit({\\n     adapter: adapter,\\n     // ... other configuration options\\n});\\n```\\n\\nUse with BotBuilder:\\n```javascript\\nconst adapter = new HangoutsAdapter({\\n     token: process.env.GOOGLE_TOKEN,\\n     google_auth_params: {\\n         credentials: process.env.GOOGLE_CREDS\\n     }\\n});\\n// set up restify...\\nconst server = restify.createServer();\\nserver.use(restify.plugins.bodyParser());\\nserver.post('/api/messages', (req, res) => {\\n     adapter.processActivity(req, res, async(context) => {\\n         // do your bot logic here!\\n     });\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 34,\n                      \"name\": \"options\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"An object containing API credentials and a webhook verification token\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 62,\n                        \"name\": \"HangoutsAdapterOptions\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 28,\n                    \"name\": \"HangoutsAdapter\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"hangouts_adapter.ts\",\n                  \"line\": 46,\n                  \"character\": 21\n                }\n              ]\n            }\n          ]\n        },\n        {\n          \"id\": 2,\n          \"name\": \"HangoutsBotWorker\",\n          \"kind\": 128,\n          \"kindString\": \"Class\",\n          \"flags\": {\n            \"isExported\": true,\n            \"isExternal\": true\n          },\n          \"comment\": {\n            \"shortText\": \"This is a specialized version of [Botkit's core BotWorker class](#BotWorker) that includes additional methods for interacting with Google Hangouts.\\nIt includes all functionality from the base class, as well as the extension methods below.\",\n            \"text\": \"When using the HangoutsAdapter with Botkit, all `bot` objects passed to handler functions will include these extensions.\\n\"\n          },\n          \"children\": [\n            {\n              \"id\": 3,\n              \"name\": \"api\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Access to the official [Google API client for Hangouts](https://www.npmjs.com/package/googleapis)\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 21,\n                  \"character\": 14\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"any\"\n              }\n            },\n            {\n              \"id\": 7,\n              \"name\": \"deleteMessage\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 8,\n                  \"name\": \"deleteMessage\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Delete an existing message.\",\n                    \"text\": \"```javascript\\n// send a reply, capture the results\\nlet sent = await bot.reply(message,'this is my original reply...');\\n\\n// delete the sent message using the sent.id field\\nawait bot.deleteMessage(sent);\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 9,\n                      \"name\": \"update\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An object in the form of `{id: <id of message to delete>}`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"BotkitMessage\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 65,\n                  \"character\": 30\n                }\n              ]\n            },\n            {\n              \"id\": 18,\n              \"name\": \"replyInThread\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 19,\n                  \"name\": \"replyInThread\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Reply to an incoming message in a brand new thread.  Works for a single message reply - if multiple replies or replying with a dialog is necessary, use [startConversationInThread](#startconversationinthread).\",\n                    \"text\": \"```javascript\\ncontroller.hears('thread','message', async(bot, message) =>{\\n     await bot.replyInThread(message,'This will appear in a new thread.');\\n});\\n```\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 20,\n                      \"name\": \"src\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An incoming message or event object\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 21,\n                      \"name\": \"resp\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A reply message containing text and/or cards\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 147,\n                  \"character\": 30\n                }\n              ]\n            },\n            {\n              \"id\": 10,\n              \"name\": \"replyWithNew\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 11,\n                  \"name\": \"replyWithNew\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Reply to a card_click event with a new message. [See Google doc for interactive cards &rarr;](https://developers.google.com/hangouts/chat/how-tos/cards-onclick#responding_to_clicks_with_a_new_or_updated_message).\",\n                    \"text\": \"When a user clicks a button contained in a card attachment, a `card_clicked` event will be emitted.\\nIn order to reply to the incoming event with a new message (rather than replacing the original card), use this method!\\n\\n```javascript\\ncontroller.on('card_clicked', async(bot, message) => {\\n     // check message.action.actionMethodName to see what button was clicked...\\n     await bot.replyWithNew(message,'Reply to button click!');\\n})\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 12,\n                      \"name\": \"src\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An incoming event object representing a card_clicked event\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 13,\n                      \"name\": \"resp\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A reply message containing text and/or cards\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"BotkitMessage\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 90,\n                  \"character\": 29\n                }\n              ]\n            },\n            {\n              \"id\": 14,\n              \"name\": \"replyWithUpdate\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 15,\n                  \"name\": \"replyWithUpdate\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Reply to a card_click event with an update to the original message. [See Google doc for interactive cards &rarr;](https://developers.google.com/hangouts/chat/how-tos/cards-onclick#responding_to_clicks_with_a_new_or_updated_message).\",\n                    \"text\": \"When a user clicks a button contained in a card attachment, a `card_clicked` event will be emitted.\\nIn order to reply to the incoming event by replacing the original message, use this method!\\n\\n```javascript\\ncontroller.on('card_clicked', async(bot, message) => {\\n     // check message.action.actionMethodName to see what button was clicked...\\n     await bot.replyWithUpdate(message,'Reply to button click!');\\n})\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 16,\n                      \"name\": \"src\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An incoming event object representing a card_clicked event\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 17,\n                      \"name\": \"resp\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A reply message containing text and/or cards\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"BotkitMessage\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 121,\n                  \"character\": 32\n                }\n              ]\n            },\n            {\n              \"id\": 22,\n              \"name\": \"startConversationInThread\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 23,\n                  \"name\": \"startConversationInThread\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Switch the bot's active context to a new thread.\\nUse this to change the location of a bot's responses or calls to beginDialog into a new conversation thread (rather than continuing in the same thread as the originating message)\",\n                    \"text\": \"```javascript\\ncontroller.hears('new thread', 'message', async(bot, message) => {\\n\\n     // change to a new thread\\n     await bot.startConversationInThread(message.channel, message.user);\\n\\n     // begin a dialog in the new thread\\n     await bot.beginDialog('foo');\\n\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 24,\n                      \"name\": \"spaceName\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"The name of the main space - usually `message.channel`\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 25,\n                      \"name\": \"userId\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"The id of the user conducting the conversation - usually `message.user`\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 26,\n                      \"name\": \"threadKey\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An optional key definining the thread - if one is not provided, a random one is generated.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 178,\n                  \"character\": 42\n                }\n              ]\n            },\n            {\n              \"id\": 4,\n              \"name\": \"updateMessage\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 5,\n                  \"name\": \"updateMessage\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Update an existing message with new content.\",\n                    \"text\": \"```javascript\\n// send a reply, capture the results\\nlet sent = await bot.reply(message,'this is my original reply...');\\n\\n// update the sent message using the sent.id field\\nawait bot.updateMessage({\\n     id: sent.id,\\n     text: 'this is an update!',\\n})\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 6,\n                      \"name\": \"update\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An object in the form `{id: <id of message to update>, text: <new text>, card: <array of card objects>}`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"BotkitMessage\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 39,\n                  \"character\": 30\n                }\n              ]\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Properties\",\n              \"kind\": 1024,\n              \"children\": [\n                3\n              ]\n            },\n            {\n              \"title\": \"Methods\",\n              \"kind\": 2048,\n              \"children\": [\n                7,\n                18,\n                10,\n                14,\n                22,\n                4\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"botworker.ts\",\n              \"line\": 17,\n              \"character\": 30\n            }\n          ],\n          \"extendedTypes\": [\n            {\n              \"type\": \"intrinsic\",\n              \"name\": \"any\"\n            }\n          ],\n          \"props\": [\n            {\n              \"id\": 3,\n              \"name\": \"api\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Access to the official [Google API client for Hangouts](https://www.npmjs.com/package/googleapis)\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 21,\n                  \"character\": 14\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"any\"\n              }\n            }\n          ],\n          \"methods\": [\n            {\n              \"id\": 7,\n              \"name\": \"deleteMessage\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 8,\n                  \"name\": \"deleteMessage\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Delete an existing message.\",\n                    \"text\": \"```javascript\\n// send a reply, capture the results\\nlet sent = await bot.reply(message,'this is my original reply...');\\n\\n// delete the sent message using the sent.id field\\nawait bot.deleteMessage(sent);\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 9,\n                      \"name\": \"update\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An object in the form of `{id: <id of message to delete>}`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"BotkitMessage\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 65,\n                  \"character\": 30\n                }\n              ]\n            },\n            {\n              \"id\": 18,\n              \"name\": \"replyInThread\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 19,\n                  \"name\": \"replyInThread\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Reply to an incoming message in a brand new thread.  Works for a single message reply - if multiple replies or replying with a dialog is necessary, use [startConversationInThread](#startconversationinthread).\",\n                    \"text\": \"```javascript\\ncontroller.hears('thread','message', async(bot, message) =>{\\n     await bot.replyInThread(message,'This will appear in a new thread.');\\n});\\n```\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 20,\n                      \"name\": \"src\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An incoming message or event object\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 21,\n                      \"name\": \"resp\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A reply message containing text and/or cards\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 147,\n                  \"character\": 30\n                }\n              ]\n            },\n            {\n              \"id\": 10,\n              \"name\": \"replyWithNew\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 11,\n                  \"name\": \"replyWithNew\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Reply to a card_click event with a new message. [See Google doc for interactive cards &rarr;](https://developers.google.com/hangouts/chat/how-tos/cards-onclick#responding_to_clicks_with_a_new_or_updated_message).\",\n                    \"text\": \"When a user clicks a button contained in a card attachment, a `card_clicked` event will be emitted.\\nIn order to reply to the incoming event with a new message (rather than replacing the original card), use this method!\\n\\n```javascript\\ncontroller.on('card_clicked', async(bot, message) => {\\n     // check message.action.actionMethodName to see what button was clicked...\\n     await bot.replyWithNew(message,'Reply to button click!');\\n})\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 12,\n                      \"name\": \"src\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An incoming event object representing a card_clicked event\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 13,\n                      \"name\": \"resp\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A reply message containing text and/or cards\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"BotkitMessage\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 90,\n                  \"character\": 29\n                }\n              ]\n            },\n            {\n              \"id\": 14,\n              \"name\": \"replyWithUpdate\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 15,\n                  \"name\": \"replyWithUpdate\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Reply to a card_click event with an update to the original message. [See Google doc for interactive cards &rarr;](https://developers.google.com/hangouts/chat/how-tos/cards-onclick#responding_to_clicks_with_a_new_or_updated_message).\",\n                    \"text\": \"When a user clicks a button contained in a card attachment, a `card_clicked` event will be emitted.\\nIn order to reply to the incoming event by replacing the original message, use this method!\\n\\n```javascript\\ncontroller.on('card_clicked', async(bot, message) => {\\n     // check message.action.actionMethodName to see what button was clicked...\\n     await bot.replyWithUpdate(message,'Reply to button click!');\\n})\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 16,\n                      \"name\": \"src\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An incoming event object representing a card_clicked event\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 17,\n                      \"name\": \"resp\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A reply message containing text and/or cards\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"BotkitMessage\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 121,\n                  \"character\": 32\n                }\n              ]\n            },\n            {\n              \"id\": 22,\n              \"name\": \"startConversationInThread\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 23,\n                  \"name\": \"startConversationInThread\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Switch the bot's active context to a new thread.\\nUse this to change the location of a bot's responses or calls to beginDialog into a new conversation thread (rather than continuing in the same thread as the originating message)\",\n                    \"text\": \"```javascript\\ncontroller.hears('new thread', 'message', async(bot, message) => {\\n\\n     // change to a new thread\\n     await bot.startConversationInThread(message.channel, message.user);\\n\\n     // begin a dialog in the new thread\\n     await bot.beginDialog('foo');\\n\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 24,\n                      \"name\": \"spaceName\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"The name of the main space - usually `message.channel`\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 25,\n                      \"name\": \"userId\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"The id of the user conducting the conversation - usually `message.user`\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 26,\n                      \"name\": \"threadKey\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isOptional\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An optional key definining the thread - if one is not provided, a random one is generated.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 178,\n                  \"character\": 42\n                }\n              ]\n            },\n            {\n              \"id\": 4,\n              \"name\": \"updateMessage\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 5,\n                  \"name\": \"updateMessage\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Update an existing message with new content.\",\n                    \"text\": \"```javascript\\n// send a reply, capture the results\\nlet sent = await bot.reply(message,'this is my original reply...');\\n\\n// update the sent message using the sent.id field\\nawait bot.updateMessage({\\n     id: sent.id,\\n     text: 'this is an update!',\\n})\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 6,\n                      \"name\": \"update\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An object in the form `{id: <id of message to update>, text: <new text>, card: <array of card objects>}`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"BotkitMessage\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 39,\n                  \"character\": 30\n                }\n              ]\n            }\n          ],\n          \"constructors\": []\n        }\n      ],\n      \"interfaces\": [\n        {\n          \"id\": 62,\n          \"name\": \"HangoutsAdapterOptions\",\n          \"kind\": 256,\n          \"kindString\": \"Interface\",\n          \"flags\": {\n            \"isExported\": true,\n            \"isExternal\": true\n          },\n          \"children\": [\n            {\n              \"id\": 68,\n              \"name\": \"enable_incomplete\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Allow the adapter to startup without a complete configuration.\\nThis is risky as it may result in a non-functioning or insecure adapter.\\nThis should only be used when getting started.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"hangouts_adapter.ts\",\n                  \"line\": 382,\n                  \"character\": 21\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"boolean\"\n              }\n            },\n            {\n              \"id\": 63,\n              \"name\": \"google_auth_params\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Parameters passed to the [Google API client library](https://www.npmjs.com/package/googleapis) which is in turn used to send messages.\\nDefine credentials per [the GoogleAuthOptions defined here](https://github.com/googleapis/google-auth-library-nodejs/blob/master/src/auth/googleauth.ts#L54),\\nOR, specify GOOGLE_APPLICATION_CREDENTIALS in environment [as described in the Google docs](https://cloud.google.com/docs/authentication/getting-started).\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"hangouts_adapter.ts\",\n                  \"line\": 366,\n                  \"character\": 22\n                }\n              ],\n              \"type\": {\n                \"type\": \"reflection\",\n                \"declaration\": {\n                  \"id\": 64,\n                  \"name\": \"__type\",\n                  \"kind\": 65536,\n                  \"kindString\": \"Type literal\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"children\": [\n                    {\n                      \"id\": 65,\n                      \"name\": \"client_email\",\n                      \"kind\": 32,\n                      \"kindString\": \"Variable\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isExternal\": true,\n                        \"isOptional\": true\n                      },\n                      \"sources\": [\n                        {\n                          \"fileName\": \"hangouts_adapter.ts\",\n                          \"line\": 367,\n                          \"character\": 20\n                        }\n                      ],\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 66,\n                      \"name\": \"private_key\",\n                      \"kind\": 32,\n                      \"kindString\": \"Variable\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isExternal\": true,\n                        \"isOptional\": true\n                      },\n                      \"sources\": [\n                        {\n                          \"fileName\": \"hangouts_adapter.ts\",\n                          \"line\": 368,\n                          \"character\": 19\n                        }\n                      ],\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"groups\": [\n                    {\n                      \"title\": \"Variables\",\n                      \"kind\": 32,\n                      \"children\": [\n                        65,\n                        66\n                      ]\n                    }\n                  ],\n                  \"sources\": [\n                    {\n                      \"fileName\": \"hangouts_adapter.ts\",\n                      \"line\": 366,\n                      \"character\": 24\n                    }\n                  ]\n                }\n              }\n            },\n            {\n              \"id\": 67,\n              \"name\": \"token\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Shared secret token used to validate the origin of incoming webhooks.\\nGet this from the [Google API console for your bot app](https://console.cloud.google.com/apis/api/chat.googleapis.com/hangouts-chat) - it is found on the Configuration tab under the heading \\\"Verification Token\\\".\\nIf defined, the origin of all incoming webhooks will be validated and any non-matching requests will be rejected.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"hangouts_adapter.ts\",\n                  \"line\": 375,\n                  \"character\": 9\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Properties\",\n              \"kind\": 1024,\n              \"children\": [\n                68,\n                63,\n                67\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"hangouts_adapter.ts\",\n              \"line\": 360,\n              \"character\": 39\n            }\n          ],\n          \"props\": [\n            {\n              \"id\": 68,\n              \"name\": \"enable_incomplete\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Allow the adapter to startup without a complete configuration.\\nThis is risky as it may result in a non-functioning or insecure adapter.\\nThis should only be used when getting started.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"hangouts_adapter.ts\",\n                  \"line\": 382,\n                  \"character\": 21\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"boolean\"\n              }\n            },\n            {\n              \"id\": 63,\n              \"name\": \"google_auth_params\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Parameters passed to the [Google API client library](https://www.npmjs.com/package/googleapis) which is in turn used to send messages.\\nDefine credentials per [the GoogleAuthOptions defined here](https://github.com/googleapis/google-auth-library-nodejs/blob/master/src/auth/googleauth.ts#L54),\\nOR, specify GOOGLE_APPLICATION_CREDENTIALS in environment [as described in the Google docs](https://cloud.google.com/docs/authentication/getting-started).\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"hangouts_adapter.ts\",\n                  \"line\": 366,\n                  \"character\": 22\n                }\n              ],\n              \"type\": {\n                \"type\": \"reflection\",\n                \"declaration\": {\n                  \"id\": 64,\n                  \"name\": \"__type\",\n                  \"kind\": 65536,\n                  \"kindString\": \"Type literal\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"children\": [\n                    {\n                      \"id\": 65,\n                      \"name\": \"client_email\",\n                      \"kind\": 32,\n                      \"kindString\": \"Variable\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isExternal\": true,\n                        \"isOptional\": true\n                      },\n                      \"sources\": [\n                        {\n                          \"fileName\": \"hangouts_adapter.ts\",\n                          \"line\": 367,\n                          \"character\": 20\n                        }\n                      ],\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 66,\n                      \"name\": \"private_key\",\n                      \"kind\": 32,\n                      \"kindString\": \"Variable\",\n                      \"flags\": {\n                        \"isExported\": true,\n                        \"isExternal\": true,\n                        \"isOptional\": true\n                      },\n                      \"sources\": [\n                        {\n                          \"fileName\": \"hangouts_adapter.ts\",\n                          \"line\": 368,\n                          \"character\": 19\n                        }\n                      ],\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"groups\": [\n                    {\n                      \"title\": \"Variables\",\n                      \"kind\": 32,\n                      \"children\": [\n                        65,\n                        66\n                      ]\n                    }\n                  ],\n                  \"sources\": [\n                    {\n                      \"fileName\": \"hangouts_adapter.ts\",\n                      \"line\": 366,\n                      \"character\": 24\n                    }\n                  ]\n                }\n              }\n            },\n            {\n              \"id\": 67,\n              \"name\": \"token\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Shared secret token used to validate the origin of incoming webhooks.\\nGet this from the [Google API console for your bot app](https://console.cloud.google.com/apis/api/chat.googleapis.com/hangouts-chat) - it is found on the Configuration tab under the heading \\\"Verification Token\\\".\\nIf defined, the origin of all incoming webhooks will be validated and any non-matching requests will be rejected.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"hangouts_adapter.ts\",\n                  \"line\": 375,\n                  \"character\": 9\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            }\n          ]\n        }\n      ]\n    },\n    {\n      \"name\": \"Botkit for Twilio SMS\",\n      \"packageName\": \"botbuilder-adapter-twilio-sms\",\n      \"path\": \"reference/twilio-sms.md\",\n      \"classes\": [\n        {\n          \"id\": 8,\n          \"name\": \"TwilioAdapter\",\n          \"kind\": 128,\n          \"kindString\": \"Class\",\n          \"flags\": {\n            \"isExported\": true,\n            \"isExternal\": true\n          },\n          \"comment\": {\n            \"shortText\": \"Connect [Botkit](https://www.npmjs.com/package/botkit) or [BotBuilder](https://www.npmjs.com/package/botbuilder) to Twilio's SMS service.\"\n          },\n          \"children\": [\n            {\n              \"id\": 12,\n              \"name\": \"constructor\",\n              \"kind\": 512,\n              \"kindString\": \"Constructor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Create an adapter to handle incoming messages from Twilio's SMS service and translate them into a standard format for processing by your bot.\",\n                \"text\": \"Use with Botkit:\\n```javascript\\nconst adapter = new TwilioAdapter({\\n     twilio_number: process.env.TWILIO_NUMBER,\\n     account_sid: process.env.TWILIO_ACCOUNT_SID,\\n     auth_token: process.env.TWILIO_AUTH_TOKEN,\\n     validation_url: process.env.TWILIO_VALIDATION_URL\\n});\\nconst controller = new Botkit({\\n     adapter: adapter,\\n     // ... other configuration options\\n});\\n```\\n\\nUse with BotBuilder:\\n```javascript\\nconst adapter = new TwilioAdapter({\\n     twilio_number: process.env.TWILIO_NUMBER,\\n     account_sid: process.env.TWILIO_ACCOUNT_SID,\\n     auth_token: process.env.TWILIO_AUTH_TOKEN,\\n     validation_url: process.env.TWILIO_VALIDATION_URL\\n});\\n// set up restify...\\nconst server = restify.createServer();\\nserver.use(restify.plugins.bodyParser());\\nserver.post('/api/messages', (req, res) => {\\n     adapter.processActivity(req, res, async(context) => {\\n         // do your bot logic here!\\n     });\\n});\\n```\\n\"\n              },\n              \"signatures\": [\n                {\n                  \"id\": 13,\n                  \"name\": \"new TwilioAdapter\",\n                  \"kind\": 16384,\n                  \"kindString\": \"Constructor signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Create an adapter to handle incoming messages from Twilio's SMS service and translate them into a standard format for processing by your bot.\",\n                    \"text\": \"Use with Botkit:\\n```javascript\\nconst adapter = new TwilioAdapter({\\n     twilio_number: process.env.TWILIO_NUMBER,\\n     account_sid: process.env.TWILIO_ACCOUNT_SID,\\n     auth_token: process.env.TWILIO_AUTH_TOKEN,\\n     validation_url: process.env.TWILIO_VALIDATION_URL\\n});\\nconst controller = new Botkit({\\n     adapter: adapter,\\n     // ... other configuration options\\n});\\n```\\n\\nUse with BotBuilder:\\n```javascript\\nconst adapter = new TwilioAdapter({\\n     twilio_number: process.env.TWILIO_NUMBER,\\n     account_sid: process.env.TWILIO_ACCOUNT_SID,\\n     auth_token: process.env.TWILIO_AUTH_TOKEN,\\n     validation_url: process.env.TWILIO_VALIDATION_URL\\n});\\n// set up restify...\\nconst server = restify.createServer();\\nserver.use(restify.plugins.bodyParser());\\nserver.post('/api/messages', (req, res) => {\\n     adapter.processActivity(req, res, async(context) => {\\n         // do your bot logic here!\\n     });\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 14,\n                      \"name\": \"options\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"An object containing API credentials, a webhook verification token and other options\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 42,\n                        \"name\": \"TwilioAdapterOptions\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 8,\n                    \"name\": \"TwilioAdapter\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"twilio_adapter.ts\",\n                  \"line\": 38,\n                  \"character\": 31\n                }\n              ]\n            },\n            {\n              \"id\": 27,\n              \"name\": \"continueConversation\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 28,\n                  \"name\": \"continueConversation\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Standard BotBuilder adapter method for continuing an existing conversation based on a conversation reference.\\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#continueconversation)\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 29,\n                      \"name\": \"reference\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A conversation reference to be applied to future messages.\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"ConversationReference\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    },\n                    {\n                      \"id\": 30,\n                      \"name\": \"logic\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A bot logic function that will perform continuing action in the form `async(context) => { ... }`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 31,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 32,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 33,\n                                  \"name\": \"context\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"name\": \"TurnContext\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"void\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"twilio_adapter.ts\",\n                              \"line\": 209,\n                              \"character\": 87\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"twilio_adapter.ts\",\n                  \"line\": 209,\n                  \"character\": 37\n                }\n              ]\n            },\n            {\n              \"id\": 34,\n              \"name\": \"processActivity\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 35,\n                  \"name\": \"processActivity\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Accept an incoming webhook request and convert it into a TurnContext which can be processed by the bot's logic.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 36,\n                      \"name\": \"req\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A request object from Restify or Express\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 37,\n                      \"name\": \"res\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A response object from Restify or Express\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 38,\n                      \"name\": \"logic\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A bot logic function in the form `async(context) => { ... }`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 39,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 40,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 41,\n                                  \"name\": \"context\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"name\": \"TurnContext\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"void\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"twilio_adapter.ts\",\n                              \"line\": 226,\n                              \"character\": 49\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"twilio_adapter.ts\",\n                  \"line\": 226,\n                  \"character\": 32\n                }\n              ]\n            },\n            {\n              \"id\": 15,\n              \"name\": \"sendActivities\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 16,\n                  \"name\": \"sendActivities\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Standard BotBuilder adapter method to send a message from the bot to the messaging API.\\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#sendactivities).\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 17,\n                      \"name\": \"context\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A TurnContext representing the current incoming message and environment. (Not used)\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"TurnContext\"\n                      }\n                    },\n                    {\n                      \"id\": 18,\n                      \"name\": \"activities\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An array of outgoing activities to be sent back to the messaging API.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"reference\",\n                          \"typeArguments\": [\n                            {\n                              \"type\": \"reference\",\n                              \"name\": \"Activity\"\n                            }\n                          ],\n                          \"name\": \"Partial\"\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"reference\",\n                          \"name\": \"ResourceResponse\"\n                        }\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"twilio_adapter.ts\",\n                  \"line\": 168,\n                  \"character\": 31\n                }\n              ]\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Constructors\",\n              \"kind\": 512,\n              \"children\": [\n                12\n              ]\n            },\n            {\n              \"title\": \"Methods\",\n              \"kind\": 2048,\n              \"children\": [\n                27,\n                34,\n                15\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"twilio_adapter.ts\",\n              \"line\": 18,\n              \"character\": 26\n            }\n          ],\n          \"extendedTypes\": [\n            {\n              \"type\": \"intrinsic\",\n              \"name\": \"any\"\n            }\n          ],\n          \"props\": [],\n          \"methods\": [\n            {\n              \"id\": 27,\n              \"name\": \"continueConversation\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 28,\n                  \"name\": \"continueConversation\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Standard BotBuilder adapter method for continuing an existing conversation based on a conversation reference.\\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#continueconversation)\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 29,\n                      \"name\": \"reference\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A conversation reference to be applied to future messages.\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"ConversationReference\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    },\n                    {\n                      \"id\": 30,\n                      \"name\": \"logic\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A bot logic function that will perform continuing action in the form `async(context) => { ... }`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 31,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 32,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 33,\n                                  \"name\": \"context\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"name\": \"TurnContext\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"void\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"twilio_adapter.ts\",\n                              \"line\": 209,\n                              \"character\": 87\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"twilio_adapter.ts\",\n                  \"line\": 209,\n                  \"character\": 37\n                }\n              ]\n            },\n            {\n              \"id\": 34,\n              \"name\": \"processActivity\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 35,\n                  \"name\": \"processActivity\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Accept an incoming webhook request and convert it into a TurnContext which can be processed by the bot's logic.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 36,\n                      \"name\": \"req\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A request object from Restify or Express\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 37,\n                      \"name\": \"res\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A response object from Restify or Express\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 38,\n                      \"name\": \"logic\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A bot logic function in the form `async(context) => { ... }`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 39,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 40,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 41,\n                                  \"name\": \"context\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"name\": \"TurnContext\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"void\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"twilio_adapter.ts\",\n                              \"line\": 226,\n                              \"character\": 49\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"twilio_adapter.ts\",\n                  \"line\": 226,\n                  \"character\": 32\n                }\n              ]\n            },\n            {\n              \"id\": 15,\n              \"name\": \"sendActivities\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 16,\n                  \"name\": \"sendActivities\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Standard BotBuilder adapter method to send a message from the bot to the messaging API.\\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#sendactivities).\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 17,\n                      \"name\": \"context\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A TurnContext representing the current incoming message and environment. (Not used)\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"TurnContext\"\n                      }\n                    },\n                    {\n                      \"id\": 18,\n                      \"name\": \"activities\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An array of outgoing activities to be sent back to the messaging API.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"reference\",\n                          \"typeArguments\": [\n                            {\n                              \"type\": \"reference\",\n                              \"name\": \"Activity\"\n                            }\n                          ],\n                          \"name\": \"Partial\"\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"reference\",\n                          \"name\": \"ResourceResponse\"\n                        }\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"twilio_adapter.ts\",\n                  \"line\": 168,\n                  \"character\": 31\n                }\n              ]\n            }\n          ],\n          \"constructors\": [\n            {\n              \"id\": 12,\n              \"name\": \"constructor\",\n              \"kind\": 512,\n              \"kindString\": \"Constructor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Create an adapter to handle incoming messages from Twilio's SMS service and translate them into a standard format for processing by your bot.\",\n                \"text\": \"Use with Botkit:\\n```javascript\\nconst adapter = new TwilioAdapter({\\n     twilio_number: process.env.TWILIO_NUMBER,\\n     account_sid: process.env.TWILIO_ACCOUNT_SID,\\n     auth_token: process.env.TWILIO_AUTH_TOKEN,\\n     validation_url: process.env.TWILIO_VALIDATION_URL\\n});\\nconst controller = new Botkit({\\n     adapter: adapter,\\n     // ... other configuration options\\n});\\n```\\n\\nUse with BotBuilder:\\n```javascript\\nconst adapter = new TwilioAdapter({\\n     twilio_number: process.env.TWILIO_NUMBER,\\n     account_sid: process.env.TWILIO_ACCOUNT_SID,\\n     auth_token: process.env.TWILIO_AUTH_TOKEN,\\n     validation_url: process.env.TWILIO_VALIDATION_URL\\n});\\n// set up restify...\\nconst server = restify.createServer();\\nserver.use(restify.plugins.bodyParser());\\nserver.post('/api/messages', (req, res) => {\\n     adapter.processActivity(req, res, async(context) => {\\n         // do your bot logic here!\\n     });\\n});\\n```\\n\"\n              },\n              \"signatures\": [\n                {\n                  \"id\": 13,\n                  \"name\": \"new TwilioAdapter\",\n                  \"kind\": 16384,\n                  \"kindString\": \"Constructor signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Create an adapter to handle incoming messages from Twilio's SMS service and translate them into a standard format for processing by your bot.\",\n                    \"text\": \"Use with Botkit:\\n```javascript\\nconst adapter = new TwilioAdapter({\\n     twilio_number: process.env.TWILIO_NUMBER,\\n     account_sid: process.env.TWILIO_ACCOUNT_SID,\\n     auth_token: process.env.TWILIO_AUTH_TOKEN,\\n     validation_url: process.env.TWILIO_VALIDATION_URL\\n});\\nconst controller = new Botkit({\\n     adapter: adapter,\\n     // ... other configuration options\\n});\\n```\\n\\nUse with BotBuilder:\\n```javascript\\nconst adapter = new TwilioAdapter({\\n     twilio_number: process.env.TWILIO_NUMBER,\\n     account_sid: process.env.TWILIO_ACCOUNT_SID,\\n     auth_token: process.env.TWILIO_AUTH_TOKEN,\\n     validation_url: process.env.TWILIO_VALIDATION_URL\\n});\\n// set up restify...\\nconst server = restify.createServer();\\nserver.use(restify.plugins.bodyParser());\\nserver.post('/api/messages', (req, res) => {\\n     adapter.processActivity(req, res, async(context) => {\\n         // do your bot logic here!\\n     });\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 14,\n                      \"name\": \"options\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"An object containing API credentials, a webhook verification token and other options\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 42,\n                        \"name\": \"TwilioAdapterOptions\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 8,\n                    \"name\": \"TwilioAdapter\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"twilio_adapter.ts\",\n                  \"line\": 38,\n                  \"character\": 31\n                }\n              ]\n            }\n          ]\n        },\n        {\n          \"id\": 2,\n          \"name\": \"TwilioBotWorker\",\n          \"kind\": 128,\n          \"kindString\": \"Class\",\n          \"flags\": {\n            \"isExported\": true,\n            \"isExternal\": true\n          },\n          \"comment\": {\n            \"shortText\": \"This is a specialized version of [Botkit's core BotWorker class](core.md#BotWorker) that includes additional methods for interacting with Twilio SMS.\\nIt includes all functionality from the base class, as well as the extension methods below.\",\n            \"text\": \"When using the TwilioAdapter with Botkit, all `bot` objects passed to handler functions will include these extensions.\\n\"\n          },\n          \"children\": [\n            {\n              \"id\": 3,\n              \"name\": \"api\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A copy of the Twilio API client.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 22,\n                  \"character\": 14\n                }\n              ],\n              \"type\": {\n                \"type\": \"reference\",\n                \"name\": \"Twilio.Twilio\"\n              }\n            },\n            {\n              \"id\": 4,\n              \"name\": \"startConversationWithUser\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 5,\n                  \"name\": \"startConversationWithUser\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Start a conversation with a given user identified by their phone number. Useful for sending pro-active messages:\",\n                    \"text\": \"```javascript\\nlet bot = await controller.spawn();\\nawait bot.startConversationWithUser(MY_PHONE_NUMBER);\\nawait bot.send('An important update!');\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 6,\n                      \"name\": \"userId\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A phone number in the form +1XXXYYYZZZZ\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 35,\n                  \"character\": 42\n                }\n              ]\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Properties\",\n              \"kind\": 1024,\n              \"children\": [\n                3\n              ]\n            },\n            {\n              \"title\": \"Methods\",\n              \"kind\": 2048,\n              \"children\": [\n                4\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"botworker.ts\",\n              \"line\": 18,\n              \"character\": 31\n            }\n          ],\n          \"extendedTypes\": [\n            {\n              \"type\": \"intrinsic\",\n              \"name\": \"any\"\n            }\n          ],\n          \"props\": [\n            {\n              \"id\": 3,\n              \"name\": \"api\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A copy of the Twilio API client.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 22,\n                  \"character\": 14\n                }\n              ],\n              \"type\": {\n                \"type\": \"reference\",\n                \"name\": \"Twilio.Twilio\"\n              }\n            }\n          ],\n          \"methods\": [\n            {\n              \"id\": 4,\n              \"name\": \"startConversationWithUser\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 5,\n                  \"name\": \"startConversationWithUser\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Start a conversation with a given user identified by their phone number. Useful for sending pro-active messages:\",\n                    \"text\": \"```javascript\\nlet bot = await controller.spawn();\\nawait bot.startConversationWithUser(MY_PHONE_NUMBER);\\nawait bot.send('An important update!');\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 6,\n                      \"name\": \"userId\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A phone number in the form +1XXXYYYZZZZ\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 35,\n                  \"character\": 42\n                }\n              ]\n            }\n          ],\n          \"constructors\": []\n        }\n      ],\n      \"interfaces\": [\n        {\n          \"id\": 42,\n          \"name\": \"TwilioAdapterOptions\",\n          \"kind\": 256,\n          \"kindString\": \"Interface\",\n          \"flags\": {\n            \"isExported\": true,\n            \"isExternal\": true\n          },\n          \"comment\": {\n            \"shortText\": \"Parameters passed to the TwilioAdapter constructor.\"\n          },\n          \"children\": [\n            {\n              \"id\": 44,\n              \"name\": \"account_sid\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"The account SID from the twilio account\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"twilio_adapter.ts\",\n                  \"line\": 317,\n                  \"character\": 15\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 45,\n              \"name\": \"auth_token\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"An api auth token associated with the twilio account\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"twilio_adapter.ts\",\n                  \"line\": 321,\n                  \"character\": 14\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 47,\n              \"name\": \"enable_incomplete\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Allow the adapter to startup without a complete configuration.\\nThis is risky as it may result in a non-functioning or insecure adapter.\\nThis should only be used when getting started.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"twilio_adapter.ts\",\n                  \"line\": 331,\n                  \"character\": 21\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"boolean\"\n              }\n            },\n            {\n              \"id\": 43,\n              \"name\": \"twilio_number\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"The phone number associated with this Twilio app, in the format 1XXXYYYZZZZ\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"twilio_adapter.ts\",\n                  \"line\": 313,\n                  \"character\": 17\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 46,\n              \"name\": \"validation_url\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"An optional url to override the automatically generated url signature used to validate incoming requests -- [See Twilio docs about securing your endpoint.](https://www.twilio.com/docs/usage/security#validating-requests)\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"twilio_adapter.ts\",\n                  \"line\": 325,\n                  \"character\": 18\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Properties\",\n              \"kind\": 1024,\n              \"children\": [\n                44,\n                45,\n                47,\n                43,\n                46\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"twilio_adapter.ts\",\n              \"line\": 309,\n              \"character\": 37\n            }\n          ],\n          \"props\": [\n            {\n              \"id\": 44,\n              \"name\": \"account_sid\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"The account SID from the twilio account\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"twilio_adapter.ts\",\n                  \"line\": 317,\n                  \"character\": 15\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 45,\n              \"name\": \"auth_token\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"An api auth token associated with the twilio account\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"twilio_adapter.ts\",\n                  \"line\": 321,\n                  \"character\": 14\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 47,\n              \"name\": \"enable_incomplete\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Allow the adapter to startup without a complete configuration.\\nThis is risky as it may result in a non-functioning or insecure adapter.\\nThis should only be used when getting started.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"twilio_adapter.ts\",\n                  \"line\": 331,\n                  \"character\": 21\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"boolean\"\n              }\n            },\n            {\n              \"id\": 43,\n              \"name\": \"twilio_number\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"The phone number associated with this Twilio app, in the format 1XXXYYYZZZZ\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"twilio_adapter.ts\",\n                  \"line\": 313,\n                  \"character\": 17\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 46,\n              \"name\": \"validation_url\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"An optional url to override the automatically generated url signature used to validate incoming requests -- [See Twilio docs about securing your endpoint.](https://www.twilio.com/docs/usage/security#validating-requests)\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"twilio_adapter.ts\",\n                  \"line\": 325,\n                  \"character\": 18\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            }\n          ]\n        }\n      ]\n    },\n    {\n      \"name\": \"Botkit for Facebook\",\n      \"packageName\": \"botbuilder-adapter-facebook\",\n      \"path\": \"reference/facebook.md\",\n      \"classes\": [\n        {\n          \"id\": 25,\n          \"name\": \"FacebookAdapter\",\n          \"kind\": 128,\n          \"kindString\": \"Class\",\n          \"flags\": {\n            \"isExported\": true,\n            \"isExternal\": true\n          },\n          \"comment\": {\n            \"shortText\": \"Connect [Botkit](https://www.npmjs.com/package/botkit) or [BotBuilder](https://www.npmjs.com/package/botbuilder) to Facebook Messenger.\"\n          },\n          \"children\": [\n            {\n              \"id\": 29,\n              \"name\": \"constructor\",\n              \"kind\": 512,\n              \"kindString\": \"Constructor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Create an adapter to handle incoming messages from Facebook and translate them into a standard format for processing by your bot.\",\n                \"text\": \"The Facebook Adapter can be used in 2 modes:\\n* bound to a single Facebook page\\n* multi-tenancy mode able to serve multiple pages\\n\\nTo create an app bound to a single Facebook page, include that page's `access_token` in the options.\\n\\nTo create an app that can be bound to multiple pages, include `getAccessTokenForPage` - a function in the form `async (pageId) => page_access_token`\\n\\nTo use with Botkit:\\n```javascript\\nconst adapter = new FacebookAdapter({\\n     verify_token: process.env.FACEBOOK_VERIFY_TOKEN,\\n     app_secret: process.env.FACEBOOK_APP_SECRET,\\n     access_token: process.env.FACEBOOK_ACCESS_TOKEN\\n});\\nconst controller = new Botkit({\\n     adapter: adapter,\\n     // other options\\n});\\n```\\n\\nTo use with BotBuilder:\\n```javascript\\nconst adapter = new FacebookAdapter({\\n     verify_token: process.env.FACEBOOK_VERIFY_TOKEN,\\n     app_secret: process.env.FACEBOOK_APP_SECRET,\\n     access_token: process.env.FACEBOOK_ACCESS_TOKEN\\n});\\nconst server = restify.createServer();\\nserver.use(restify.plugins.bodyParser());\\nserver.post('/api/messages', (req, res) => {\\n     adapter.processActivity(req, res, async(context) => {\\n         // do your bot logic here!\\n     });\\n});\\n```\\n\\nIn multi-tenancy mode:\\n```javascript\\nconst adapter = new FacebookAdapter({\\n     verify_token: process.env.FACEBOOK_VERIFY_TOKEN,\\n     app_secret: process.env.FACEBOOK_APP_SECRET,\\n      getAccessTokenForPage: async(pageId) => {\\n          // do something to fetch the page access token for pageId.\\n          return token;\\n      })\\n});\\n```\\n\"\n              },\n              \"signatures\": [\n                {\n                  \"id\": 30,\n                  \"name\": \"new FacebookAdapter\",\n                  \"kind\": 16384,\n                  \"kindString\": \"Constructor signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Create an adapter to handle incoming messages from Facebook and translate them into a standard format for processing by your bot.\",\n                    \"text\": \"The Facebook Adapter can be used in 2 modes:\\n* bound to a single Facebook page\\n* multi-tenancy mode able to serve multiple pages\\n\\nTo create an app bound to a single Facebook page, include that page's `access_token` in the options.\\n\\nTo create an app that can be bound to multiple pages, include `getAccessTokenForPage` - a function in the form `async (pageId) => page_access_token`\\n\\nTo use with Botkit:\\n```javascript\\nconst adapter = new FacebookAdapter({\\n     verify_token: process.env.FACEBOOK_VERIFY_TOKEN,\\n     app_secret: process.env.FACEBOOK_APP_SECRET,\\n     access_token: process.env.FACEBOOK_ACCESS_TOKEN\\n});\\nconst controller = new Botkit({\\n     adapter: adapter,\\n     // other options\\n});\\n```\\n\\nTo use with BotBuilder:\\n```javascript\\nconst adapter = new FacebookAdapter({\\n     verify_token: process.env.FACEBOOK_VERIFY_TOKEN,\\n     app_secret: process.env.FACEBOOK_APP_SECRET,\\n     access_token: process.env.FACEBOOK_ACCESS_TOKEN\\n});\\nconst server = restify.createServer();\\nserver.use(restify.plugins.bodyParser());\\nserver.post('/api/messages', (req, res) => {\\n     adapter.processActivity(req, res, async(context) => {\\n         // do your bot logic here!\\n     });\\n});\\n```\\n\\nIn multi-tenancy mode:\\n```javascript\\nconst adapter = new FacebookAdapter({\\n     verify_token: process.env.FACEBOOK_VERIFY_TOKEN,\\n     app_secret: process.env.FACEBOOK_APP_SECRET,\\n      getAccessTokenForPage: async(pageId) => {\\n          // do something to fetch the page access token for pageId.\\n          return token;\\n      })\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 31,\n                      \"name\": \"options\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"Configuration options\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 65,\n                        \"name\": \"FacebookAdapterOptions\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 25,\n                    \"name\": \"FacebookAdapter\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"facebook_adapter.ts\",\n                  \"line\": 38,\n                  \"character\": 44\n                }\n              ]\n            },\n            {\n              \"id\": 50,\n              \"name\": \"continueConversation\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 51,\n                  \"name\": \"continueConversation\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Standard BotBuilder adapter method for continuing an existing conversation based on a conversation reference.\\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#continueconversation)\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 52,\n                      \"name\": \"reference\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A conversation reference to be applied to future messages.\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"ConversationReference\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    },\n                    {\n                      \"id\": 53,\n                      \"name\": \"logic\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A bot logic function that will perform continuing action in the form `async(context) => { ... }`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 54,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 55,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 56,\n                                  \"name\": \"context\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"name\": \"TurnContext\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"void\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"facebook_adapter.ts\",\n                              \"line\": 323,\n                              \"character\": 87\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"facebook_adapter.ts\",\n                  \"line\": 323,\n                  \"character\": 37\n                }\n              ]\n            },\n            {\n              \"id\": 35,\n              \"name\": \"getAPI\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 36,\n                  \"name\": \"getAPI\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Get a Facebook API client with the correct credentials based on the page identified in the incoming activity.\\nThis is used by many internal functions to get access to the Facebook API, and is exposed as `bot.api` on any BotWorker instances passed into Botkit handler functions.\",\n                    \"text\": \"```javascript\\nlet api = adapter.getAPI(activity);\\nlet res = api.callAPI('/me/messages', 'POST', message);\\n```\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 37,\n                      \"name\": \"activity\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An incoming message activity\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"Activity\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"reference\",\n                        \"id\": 2,\n                        \"name\": \"FacebookAPI\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"facebook_adapter.ts\",\n                  \"line\": 174,\n                  \"character\": 23\n                }\n              ]\n            },\n            {\n              \"id\": 32,\n              \"name\": \"init\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 33,\n                  \"name\": \"init\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Botkit-only: Initialization function called automatically when used with Botkit.\\n     * Amends the webhook_uri with an additional behavior for responding to Facebook's webhook verification request.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 34,\n                      \"name\": \"botkit\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"facebook_adapter.ts\",\n                  \"line\": 149,\n                  \"character\": 21\n                }\n              ]\n            },\n            {\n              \"id\": 57,\n              \"name\": \"processActivity\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 58,\n                  \"name\": \"processActivity\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Accept an incoming webhook request and convert it into a TurnContext which can be processed by the bot's logic.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 59,\n                      \"name\": \"req\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A request object from Restify or Express\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 60,\n                      \"name\": \"res\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A response object from Restify or Express\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 61,\n                      \"name\": \"logic\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A bot logic function in the form `async(context) => { ... }`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 62,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 63,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 64,\n                                  \"name\": \"context\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"name\": \"TurnContext\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"void\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"facebook_adapter.ts\",\n                              \"line\": 340,\n                              \"character\": 49\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"facebook_adapter.ts\",\n                  \"line\": 340,\n                  \"character\": 32\n                }\n              ]\n            },\n            {\n              \"id\": 38,\n              \"name\": \"sendActivities\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 39,\n                  \"name\": \"sendActivities\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Standard BotBuilder adapter method to send a message from the bot to the messaging API.\\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#sendactivities).\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 40,\n                      \"name\": \"context\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A TurnContext representing the current incoming message and environment.\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"TurnContext\"\n                      }\n                    },\n                    {\n                      \"id\": 41,\n                      \"name\": \"activities\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An array of outgoing activities to be sent back to the messaging API.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"reference\",\n                          \"typeArguments\": [\n                            {\n                              \"type\": \"reference\",\n                              \"name\": \"Activity\"\n                            }\n                          ],\n                          \"name\": \"Partial\"\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"reference\",\n                          \"name\": \"ResourceResponse\"\n                        }\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"facebook_adapter.ts\",\n                  \"line\": 274,\n                  \"character\": 31\n                }\n              ]\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Constructors\",\n              \"kind\": 512,\n              \"children\": [\n                29\n              ]\n            },\n            {\n              \"title\": \"Methods\",\n              \"kind\": 2048,\n              \"children\": [\n                50,\n                35,\n                32,\n                57,\n                38\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"facebook_adapter.ts\",\n              \"line\": 19,\n              \"character\": 28\n            }\n          ],\n          \"extendedTypes\": [\n            {\n              \"type\": \"intrinsic\",\n              \"name\": \"any\"\n            }\n          ],\n          \"props\": [],\n          \"methods\": [\n            {\n              \"id\": 50,\n              \"name\": \"continueConversation\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 51,\n                  \"name\": \"continueConversation\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Standard BotBuilder adapter method for continuing an existing conversation based on a conversation reference.\\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#continueconversation)\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 52,\n                      \"name\": \"reference\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A conversation reference to be applied to future messages.\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"ConversationReference\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    },\n                    {\n                      \"id\": 53,\n                      \"name\": \"logic\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A bot logic function that will perform continuing action in the form `async(context) => { ... }`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 54,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 55,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 56,\n                                  \"name\": \"context\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"name\": \"TurnContext\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"void\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"facebook_adapter.ts\",\n                              \"line\": 323,\n                              \"character\": 87\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"facebook_adapter.ts\",\n                  \"line\": 323,\n                  \"character\": 37\n                }\n              ]\n            },\n            {\n              \"id\": 35,\n              \"name\": \"getAPI\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 36,\n                  \"name\": \"getAPI\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Get a Facebook API client with the correct credentials based on the page identified in the incoming activity.\\nThis is used by many internal functions to get access to the Facebook API, and is exposed as `bot.api` on any BotWorker instances passed into Botkit handler functions.\",\n                    \"text\": \"```javascript\\nlet api = adapter.getAPI(activity);\\nlet res = api.callAPI('/me/messages', 'POST', message);\\n```\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 37,\n                      \"name\": \"activity\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An incoming message activity\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"Activity\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"reference\",\n                        \"id\": 2,\n                        \"name\": \"FacebookAPI\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"facebook_adapter.ts\",\n                  \"line\": 174,\n                  \"character\": 23\n                }\n              ]\n            },\n            {\n              \"id\": 32,\n              \"name\": \"init\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 33,\n                  \"name\": \"init\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Botkit-only: Initialization function called automatically when used with Botkit.\\n     * Amends the webhook_uri with an additional behavior for responding to Facebook's webhook verification request.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 34,\n                      \"name\": \"botkit\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"facebook_adapter.ts\",\n                  \"line\": 149,\n                  \"character\": 21\n                }\n              ]\n            },\n            {\n              \"id\": 57,\n              \"name\": \"processActivity\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 58,\n                  \"name\": \"processActivity\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Accept an incoming webhook request and convert it into a TurnContext which can be processed by the bot's logic.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 59,\n                      \"name\": \"req\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A request object from Restify or Express\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 60,\n                      \"name\": \"res\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A response object from Restify or Express\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    },\n                    {\n                      \"id\": 61,\n                      \"name\": \"logic\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A bot logic function in the form `async(context) => { ... }`\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 62,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 63,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 64,\n                                  \"name\": \"context\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"name\": \"TurnContext\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"void\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"facebook_adapter.ts\",\n                              \"line\": 340,\n                              \"character\": 49\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"facebook_adapter.ts\",\n                  \"line\": 340,\n                  \"character\": 32\n                }\n              ]\n            },\n            {\n              \"id\": 38,\n              \"name\": \"sendActivities\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 39,\n                  \"name\": \"sendActivities\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Standard BotBuilder adapter method to send a message from the bot to the messaging API.\\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#sendactivities).\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 40,\n                      \"name\": \"context\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A TurnContext representing the current incoming message and environment.\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"TurnContext\"\n                      }\n                    },\n                    {\n                      \"id\": 41,\n                      \"name\": \"activities\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An array of outgoing activities to be sent back to the messaging API.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"reference\",\n                          \"typeArguments\": [\n                            {\n                              \"type\": \"reference\",\n                              \"name\": \"Activity\"\n                            }\n                          ],\n                          \"name\": \"Partial\"\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"array\",\n                        \"elementType\": {\n                          \"type\": \"reference\",\n                          \"name\": \"ResourceResponse\"\n                        }\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"facebook_adapter.ts\",\n                  \"line\": 274,\n                  \"character\": 31\n                }\n              ]\n            }\n          ],\n          \"constructors\": [\n            {\n              \"id\": 29,\n              \"name\": \"constructor\",\n              \"kind\": 512,\n              \"kindString\": \"Constructor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Create an adapter to handle incoming messages from Facebook and translate them into a standard format for processing by your bot.\",\n                \"text\": \"The Facebook Adapter can be used in 2 modes:\\n* bound to a single Facebook page\\n* multi-tenancy mode able to serve multiple pages\\n\\nTo create an app bound to a single Facebook page, include that page's `access_token` in the options.\\n\\nTo create an app that can be bound to multiple pages, include `getAccessTokenForPage` - a function in the form `async (pageId) => page_access_token`\\n\\nTo use with Botkit:\\n```javascript\\nconst adapter = new FacebookAdapter({\\n     verify_token: process.env.FACEBOOK_VERIFY_TOKEN,\\n     app_secret: process.env.FACEBOOK_APP_SECRET,\\n     access_token: process.env.FACEBOOK_ACCESS_TOKEN\\n});\\nconst controller = new Botkit({\\n     adapter: adapter,\\n     // other options\\n});\\n```\\n\\nTo use with BotBuilder:\\n```javascript\\nconst adapter = new FacebookAdapter({\\n     verify_token: process.env.FACEBOOK_VERIFY_TOKEN,\\n     app_secret: process.env.FACEBOOK_APP_SECRET,\\n     access_token: process.env.FACEBOOK_ACCESS_TOKEN\\n});\\nconst server = restify.createServer();\\nserver.use(restify.plugins.bodyParser());\\nserver.post('/api/messages', (req, res) => {\\n     adapter.processActivity(req, res, async(context) => {\\n         // do your bot logic here!\\n     });\\n});\\n```\\n\\nIn multi-tenancy mode:\\n```javascript\\nconst adapter = new FacebookAdapter({\\n     verify_token: process.env.FACEBOOK_VERIFY_TOKEN,\\n     app_secret: process.env.FACEBOOK_APP_SECRET,\\n      getAccessTokenForPage: async(pageId) => {\\n          // do something to fetch the page access token for pageId.\\n          return token;\\n      })\\n});\\n```\\n\"\n              },\n              \"signatures\": [\n                {\n                  \"id\": 30,\n                  \"name\": \"new FacebookAdapter\",\n                  \"kind\": 16384,\n                  \"kindString\": \"Constructor signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Create an adapter to handle incoming messages from Facebook and translate them into a standard format for processing by your bot.\",\n                    \"text\": \"The Facebook Adapter can be used in 2 modes:\\n* bound to a single Facebook page\\n* multi-tenancy mode able to serve multiple pages\\n\\nTo create an app bound to a single Facebook page, include that page's `access_token` in the options.\\n\\nTo create an app that can be bound to multiple pages, include `getAccessTokenForPage` - a function in the form `async (pageId) => page_access_token`\\n\\nTo use with Botkit:\\n```javascript\\nconst adapter = new FacebookAdapter({\\n     verify_token: process.env.FACEBOOK_VERIFY_TOKEN,\\n     app_secret: process.env.FACEBOOK_APP_SECRET,\\n     access_token: process.env.FACEBOOK_ACCESS_TOKEN\\n});\\nconst controller = new Botkit({\\n     adapter: adapter,\\n     // other options\\n});\\n```\\n\\nTo use with BotBuilder:\\n```javascript\\nconst adapter = new FacebookAdapter({\\n     verify_token: process.env.FACEBOOK_VERIFY_TOKEN,\\n     app_secret: process.env.FACEBOOK_APP_SECRET,\\n     access_token: process.env.FACEBOOK_ACCESS_TOKEN\\n});\\nconst server = restify.createServer();\\nserver.use(restify.plugins.bodyParser());\\nserver.post('/api/messages', (req, res) => {\\n     adapter.processActivity(req, res, async(context) => {\\n         // do your bot logic here!\\n     });\\n});\\n```\\n\\nIn multi-tenancy mode:\\n```javascript\\nconst adapter = new FacebookAdapter({\\n     verify_token: process.env.FACEBOOK_VERIFY_TOKEN,\\n     app_secret: process.env.FACEBOOK_APP_SECRET,\\n      getAccessTokenForPage: async(pageId) => {\\n          // do something to fetch the page access token for pageId.\\n          return token;\\n      })\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 31,\n                      \"name\": \"options\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"Configuration options\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 65,\n                        \"name\": \"FacebookAdapterOptions\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 25,\n                    \"name\": \"FacebookAdapter\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"facebook_adapter.ts\",\n                  \"line\": 38,\n                  \"character\": 44\n                }\n              ]\n            }\n          ]\n        },\n        {\n          \"id\": 15,\n          \"name\": \"FacebookBotWorker\",\n          \"kind\": 128,\n          \"kindString\": \"Class\",\n          \"flags\": {\n            \"isExported\": true,\n            \"isExternal\": true\n          },\n          \"comment\": {\n            \"shortText\": \"This is a specialized version of [Botkit's core BotWorker class](core.md#BotWorker) that includes additional methods for interacting with Facebook.\\nIt includes all functionality from the base class, as well as the extension methods below.\",\n            \"text\": \"When using the FacebookAdapter with Botkit, all `bot` objects passed to handler functions will include these extensions.\\n\"\n          },\n          \"children\": [\n            {\n              \"id\": 17,\n              \"name\": \"constructor\",\n              \"kind\": 512,\n              \"kindString\": \"Constructor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Reserved for use internally by Botkit's `controller.spawn()`, this class is used to create a BotWorker instance that can send messages, replies, and make other API calls.\",\n                \"text\": \"When used with the FacebookAdapter's multi-tenancy mode, it is possible to spawn a bot instance by passing in the Facebook page ID representing the appropriate bot identity.\\nUse this in concert with [startConversationWithUser()](#startConversationWithUser) and [changeContext()](core.md#changecontext) to start conversations\\nor send proactive alerts to users on a schedule or in response to external events.\\n\\n```javascript\\nlet bot = await controller.spawn(FACEBOOK_PAGE_ID);\\n```\"\n              },\n              \"signatures\": [\n                {\n                  \"id\": 18,\n                  \"name\": \"new FacebookBotWorker\",\n                  \"kind\": 16384,\n                  \"kindString\": \"Constructor signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Reserved for use internally by Botkit's `controller.spawn()`, this class is used to create a BotWorker instance that can send messages, replies, and make other API calls.\",\n                    \"text\": \"When used with the FacebookAdapter's multi-tenancy mode, it is possible to spawn a bot instance by passing in the Facebook page ID representing the appropriate bot identity.\\nUse this in concert with [startConversationWithUser()](#startConversationWithUser) and [changeContext()](core.md#changecontext) to start conversations\\nor send proactive alerts to users on a schedule or in response to external events.\\n\\n```javascript\\nlet bot = await controller.spawn(FACEBOOK_PAGE_ID);\\n```\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 19,\n                      \"name\": \"botkit\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"The Botkit controller object responsible for spawning this bot worker.\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"Botkit\"\n                      }\n                    },\n                    {\n                      \"id\": 20,\n                      \"name\": \"config\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"Normally, a DialogContext object.  Can also be the ID of a Facebook page managed by this app.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 15,\n                    \"name\": \"FacebookBotWorker\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 22,\n                  \"character\": 28\n                }\n              ]\n            },\n            {\n              \"id\": 16,\n              \"name\": \"api\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A copy of the FacebookAPI client giving access to `let res = await bot.api.callAPI(path, method, parameters);`\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 22,\n                  \"character\": 14\n                }\n              ],\n              \"type\": {\n                \"type\": \"reference\",\n                \"id\": 2,\n                \"name\": \"FacebookAPI\"\n              }\n            },\n            {\n              \"id\": 21,\n              \"name\": \"startConversationWithUser\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 22,\n                  \"name\": \"startConversationWithUser\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Change the operating context of the worker to begin a conversation with a specific user.\\nAfter calling this method, any calls to `bot.say()` or `bot.beginDialog()` will occur in this new context.\",\n                    \"text\": \"This method can be used to send users scheduled messages or messages triggered by external events.\\n```javascript\\nlet bot = await controller.spawn(FACEBOOK_PAGE_ID);\\nawait bot.startConversationWithUser(FACEBOOK_USER_PSID);\\nawait bot.say('Howdy human!');\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 23,\n                      \"name\": \"userId\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"the PSID of a user the bot has previously interacted with\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 70,\n                  \"character\": 42\n                }\n              ]\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Constructors\",\n              \"kind\": 512,\n              \"children\": [\n                17\n              ]\n            },\n            {\n              \"title\": \"Properties\",\n              \"kind\": 1024,\n              \"children\": [\n                16\n              ]\n            },\n            {\n              \"title\": \"Methods\",\n              \"kind\": 2048,\n              \"children\": [\n                21\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"botworker.ts\",\n              \"line\": 18,\n              \"character\": 30\n            }\n          ],\n          \"extendedTypes\": [\n            {\n              \"type\": \"intrinsic\",\n              \"name\": \"any\"\n            }\n          ],\n          \"props\": [\n            {\n              \"id\": 16,\n              \"name\": \"api\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"A copy of the FacebookAPI client giving access to `let res = await bot.api.callAPI(path, method, parameters);`\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 22,\n                  \"character\": 14\n                }\n              ],\n              \"type\": {\n                \"type\": \"reference\",\n                \"id\": 2,\n                \"name\": \"FacebookAPI\"\n              }\n            }\n          ],\n          \"methods\": [\n            {\n              \"id\": 21,\n              \"name\": \"startConversationWithUser\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 22,\n                  \"name\": \"startConversationWithUser\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Change the operating context of the worker to begin a conversation with a specific user.\\nAfter calling this method, any calls to `bot.say()` or `bot.beginDialog()` will occur in this new context.\",\n                    \"text\": \"This method can be used to send users scheduled messages or messages triggered by external events.\\n```javascript\\nlet bot = await controller.spawn(FACEBOOK_PAGE_ID);\\nawait bot.startConversationWithUser(FACEBOOK_USER_PSID);\\nawait bot.say('Howdy human!');\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 23,\n                      \"name\": \"userId\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"the PSID of a user the bot has previously interacted with\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 70,\n                  \"character\": 42\n                }\n              ]\n            }\n          ],\n          \"constructors\": [\n            {\n              \"id\": 17,\n              \"name\": \"constructor\",\n              \"kind\": 512,\n              \"kindString\": \"Constructor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Reserved for use internally by Botkit's `controller.spawn()`, this class is used to create a BotWorker instance that can send messages, replies, and make other API calls.\",\n                \"text\": \"When used with the FacebookAdapter's multi-tenancy mode, it is possible to spawn a bot instance by passing in the Facebook page ID representing the appropriate bot identity.\\nUse this in concert with [startConversationWithUser()](#startConversationWithUser) and [changeContext()](core.md#changecontext) to start conversations\\nor send proactive alerts to users on a schedule or in response to external events.\\n\\n```javascript\\nlet bot = await controller.spawn(FACEBOOK_PAGE_ID);\\n```\"\n              },\n              \"signatures\": [\n                {\n                  \"id\": 18,\n                  \"name\": \"new FacebookBotWorker\",\n                  \"kind\": 16384,\n                  \"kindString\": \"Constructor signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Reserved for use internally by Botkit's `controller.spawn()`, this class is used to create a BotWorker instance that can send messages, replies, and make other API calls.\",\n                    \"text\": \"When used with the FacebookAdapter's multi-tenancy mode, it is possible to spawn a bot instance by passing in the Facebook page ID representing the appropriate bot identity.\\nUse this in concert with [startConversationWithUser()](#startConversationWithUser) and [changeContext()](core.md#changecontext) to start conversations\\nor send proactive alerts to users on a schedule or in response to external events.\\n\\n```javascript\\nlet bot = await controller.spawn(FACEBOOK_PAGE_ID);\\n```\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 19,\n                      \"name\": \"botkit\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"The Botkit controller object responsible for spawning this bot worker.\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"Botkit\"\n                      }\n                    },\n                    {\n                      \"id\": 20,\n                      \"name\": \"config\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"Normally, a DialogContext object.  Can also be the ID of a Facebook page managed by this app.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 15,\n                    \"name\": \"FacebookBotWorker\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"botworker.ts\",\n                  \"line\": 22,\n                  \"character\": 28\n                }\n              ]\n            }\n          ]\n        },\n        {\n          \"id\": 2,\n          \"name\": \"FacebookAPI\",\n          \"kind\": 128,\n          \"kindString\": \"Class\",\n          \"flags\": {\n            \"isExported\": true,\n            \"isExternal\": true\n          },\n          \"comment\": {\n            \"shortText\": \"A simple API client for the Facebook API.  Automatically signs requests with the access token and app secret proof.\\nIt can be used to call any API provided by Facebook.\"\n          },\n          \"children\": [\n            {\n              \"id\": 3,\n              \"name\": \"constructor\",\n              \"kind\": 512,\n              \"kindString\": \"Constructor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Create a FacebookAPI client.\\n```\\nlet api = new FacebookAPI(TOKEN, SECRET);\\nawait api.callAPI('/some/api','POST', {some_options});\\n```\"\n              },\n              \"signatures\": [\n                {\n                  \"id\": 4,\n                  \"name\": \"new FacebookAPI\",\n                  \"kind\": 16384,\n                  \"kindString\": \"Constructor signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Create a FacebookAPI client.\\n```\\nlet api = new FacebookAPI(TOKEN, SECRET);\\nawait api.callAPI('/some/api','POST', {some_options});\\n```\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 5,\n                      \"name\": \"token\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"a page access token\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 6,\n                      \"name\": \"secret\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"an app secret\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 7,\n                      \"name\": \"api_host\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"optional root hostname for constructing api calls, defaults to graph.facebook.com\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      },\n                      \"defaultValue\": \"\\\"graph.facebook.com\\\"\"\n                    },\n                    {\n                      \"id\": 8,\n                      \"name\": \"api_version\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"optional api version used when constructing api calls, defaults to v3.2\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      },\n                      \"defaultValue\": \"\\\"v3.2\\\"\"\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 2,\n                    \"name\": \"FacebookAPI\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"facebook_api.ts\",\n                  \"line\": 21,\n                  \"character\": 32\n                }\n              ]\n            },\n            {\n              \"id\": 9,\n              \"name\": \"callAPI\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 10,\n                  \"name\": \"callAPI\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Call one of the Facebook APIs\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 11,\n                      \"name\": \"path\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"Path to the API endpoint, for example `/me/messages`\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 12,\n                      \"name\": \"method\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"HTTP method, for example POST, GET, DELETE or PUT.\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      },\n                      \"defaultValue\": \"\\\"POST\\\"\"\n                    },\n                    {\n                      \"id\": 13,\n                      \"name\": \"payload\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An object to be sent as parameters to the API call.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      },\n                      \"defaultValue\": \"{}\"\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"facebook_api.ts\",\n                  \"line\": 50,\n                  \"character\": 24\n                }\n              ]\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Constructors\",\n              \"kind\": 512,\n              \"children\": [\n                3\n              ]\n            },\n            {\n              \"title\": \"Methods\",\n              \"kind\": 2048,\n              \"children\": [\n                9\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"facebook_api.ts\",\n              \"line\": 17,\n              \"character\": 24\n            }\n          ],\n          \"props\": [],\n          \"methods\": [\n            {\n              \"id\": 9,\n              \"name\": \"callAPI\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 10,\n                  \"name\": \"callAPI\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Call one of the Facebook APIs\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 11,\n                      \"name\": \"path\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"Path to the API endpoint, for example `/me/messages`\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 12,\n                      \"name\": \"method\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"HTTP method, for example POST, GET, DELETE or PUT.\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      },\n                      \"defaultValue\": \"\\\"POST\\\"\"\n                    },\n                    {\n                      \"id\": 13,\n                      \"name\": \"payload\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An object to be sent as parameters to the API call.\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      },\n                      \"defaultValue\": \"{}\"\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"facebook_api.ts\",\n                  \"line\": 50,\n                  \"character\": 24\n                }\n              ]\n            }\n          ],\n          \"constructors\": [\n            {\n              \"id\": 3,\n              \"name\": \"constructor\",\n              \"kind\": 512,\n              \"kindString\": \"Constructor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Create a FacebookAPI client.\\n```\\nlet api = new FacebookAPI(TOKEN, SECRET);\\nawait api.callAPI('/some/api','POST', {some_options});\\n```\"\n              },\n              \"signatures\": [\n                {\n                  \"id\": 4,\n                  \"name\": \"new FacebookAPI\",\n                  \"kind\": 16384,\n                  \"kindString\": \"Constructor signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Create a FacebookAPI client.\\n```\\nlet api = new FacebookAPI(TOKEN, SECRET);\\nawait api.callAPI('/some/api','POST', {some_options});\\n```\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 5,\n                      \"name\": \"token\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"a page access token\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 6,\n                      \"name\": \"secret\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"an app secret\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 7,\n                      \"name\": \"api_host\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"optional root hostname for constructing api calls, defaults to graph.facebook.com\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      },\n                      \"defaultValue\": \"\\\"graph.facebook.com\\\"\"\n                    },\n                    {\n                      \"id\": 8,\n                      \"name\": \"api_version\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"shortText\": \"optional api version used when constructing api calls, defaults to v3.2\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      },\n                      \"defaultValue\": \"\\\"v3.2\\\"\"\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 2,\n                    \"name\": \"FacebookAPI\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"facebook_api.ts\",\n                  \"line\": 21,\n                  \"character\": 32\n                }\n              ]\n            }\n          ]\n        },\n        {\n          \"id\": 78,\n          \"name\": \"FacebookEventTypeMiddleware\",\n          \"kind\": 128,\n          \"kindString\": \"Class\",\n          \"flags\": {\n            \"isExported\": true,\n            \"isExternal\": true\n          },\n          \"comment\": {\n            \"shortText\": \"This adapter middleware, when used in conjunction with FacebookAdapter and Botkit, will result in Botkit emitting events with\\nnames based on their event type.\",\n            \"text\": \"```javascript\\nconst adapter = new FacebookAdapter(MY_OPTIONS);\\nadapter.use(new FacebookEventTypeMiddleware());\\nconst controller = new Botkit({\\n     adapter: adapter,\\n});\\n\\n// define a handler for one of the new events\\ncontroller.on('facebook_option', async(bot, message) => {\\n     // ...\\n});\\n```\\n\\nWhen used, events emitted may include:\\n* facebook_postback\\n* facebook_referral\\n* facebook_optin\\n* message_delivered\\n* message_read\\n* facebook_account_linking\\n* message_echo\\n* facebook_app_roles\\n* standby\\n* facebook_receive_thread_control\\n* facebook_request_thread_control\\n\\n\"\n          },\n          \"sources\": [\n            {\n              \"fileName\": \"facebook_event_middleware.ts\",\n              \"line\": 42,\n              \"character\": 40\n            }\n          ],\n          \"extendedTypes\": [\n            {\n              \"type\": \"intrinsic\",\n              \"name\": \"any\"\n            }\n          ]\n        }\n      ],\n      \"interfaces\": [\n        {\n          \"id\": 65,\n          \"name\": \"FacebookAdapterOptions\",\n          \"kind\": 256,\n          \"kindString\": \"Interface\",\n          \"flags\": {\n            \"isExported\": true,\n            \"isExternal\": true\n          },\n          \"comment\": {\n            \"shortText\": \"This interface defines the options that can be passed into the FacebookAdapter constructor function.\"\n          },\n          \"children\": [\n            {\n              \"id\": 70,\n              \"name\": \"access_token\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"When bound to a single page, use `access_token` to specify the \\\"page access token\\\" provided in the Facebook developer portal's \\\"Access Tokens\\\" widget of the \\\"Messenger Settings\\\" page.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"facebook_adapter.ts\",\n                  \"line\": 476,\n                  \"character\": 16\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 66,\n              \"name\": \"api_host\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Alternate root url used to contruct calls to Facebook's API.  Defaults to 'graph.facebook.com' but can be changed (for mocking, proxy, etc).\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"facebook_adapter.ts\",\n                  \"line\": 457,\n                  \"character\": 12\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 67,\n              \"name\": \"api_version\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Alternate API version used to construct calls to Facebook's API. Defaults to v3.2\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"facebook_adapter.ts\",\n                  \"line\": 461,\n                  \"character\": 15\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 69,\n              \"name\": \"app_secret\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"The \\\"app secret\\\" from the \\\"basic settings\\\" page from your app's configuration in the Facebook developer portal\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"facebook_adapter.ts\",\n                  \"line\": 471,\n                  \"character\": 14\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 75,\n              \"name\": \"enable_incomplete\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Allow the adapter to startup without a complete configuration.\\nThis is risky as it may result in a non-functioning or insecure adapter.\\nThis should only be used when getting started.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"facebook_adapter.ts\",\n                  \"line\": 488,\n                  \"character\": 21\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"boolean\"\n              }\n            },\n            {\n              \"id\": 71,\n              \"name\": \"getAccessTokenForPage\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"When bound to multiple teams, provide a function that, given a page id, will return the page access token for that page.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"facebook_adapter.ts\",\n                  \"line\": 481,\n                  \"character\": 25\n                }\n              ],\n              \"type\": {\n                \"type\": \"reflection\",\n                \"declaration\": {\n                  \"id\": 72,\n                  \"name\": \"__type\",\n                  \"kind\": 65536,\n                  \"kindString\": \"Type literal\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"signatures\": [\n                    {\n                      \"id\": 73,\n                      \"name\": \"__call\",\n                      \"kind\": 4096,\n                      \"kindString\": \"Call signature\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"parameters\": [\n                        {\n                          \"id\": 74,\n                          \"name\": \"pageId\",\n                          \"kind\": 32768,\n                          \"kindString\": \"Parameter\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"type\": {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        }\n                      ],\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        ],\n                        \"name\": \"Promise\"\n                      }\n                    }\n                  ],\n                  \"sources\": [\n                    {\n                      \"fileName\": \"facebook_adapter.ts\",\n                      \"line\": 481,\n                      \"character\": 27\n                    }\n                  ]\n                }\n              }\n            },\n            {\n              \"id\": 68,\n              \"name\": \"verify_token\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"The \\\"verify token\\\" used to initially create and verify the Webhooks subscription settings on Facebook's developer portal.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"facebook_adapter.ts\",\n                  \"line\": 466,\n                  \"character\": 16\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Properties\",\n              \"kind\": 1024,\n              \"children\": [\n                70,\n                66,\n                67,\n                69,\n                75,\n                71,\n                68\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"facebook_adapter.ts\",\n              \"line\": 453,\n              \"character\": 39\n            }\n          ],\n          \"props\": [\n            {\n              \"id\": 70,\n              \"name\": \"access_token\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"When bound to a single page, use `access_token` to specify the \\\"page access token\\\" provided in the Facebook developer portal's \\\"Access Tokens\\\" widget of the \\\"Messenger Settings\\\" page.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"facebook_adapter.ts\",\n                  \"line\": 476,\n                  \"character\": 16\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 66,\n              \"name\": \"api_host\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Alternate root url used to contruct calls to Facebook's API.  Defaults to 'graph.facebook.com' but can be changed (for mocking, proxy, etc).\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"facebook_adapter.ts\",\n                  \"line\": 457,\n                  \"character\": 12\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 67,\n              \"name\": \"api_version\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Alternate API version used to construct calls to Facebook's API. Defaults to v3.2\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"facebook_adapter.ts\",\n                  \"line\": 461,\n                  \"character\": 15\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 69,\n              \"name\": \"app_secret\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"The \\\"app secret\\\" from the \\\"basic settings\\\" page from your app's configuration in the Facebook developer portal\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"facebook_adapter.ts\",\n                  \"line\": 471,\n                  \"character\": 14\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 75,\n              \"name\": \"enable_incomplete\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Allow the adapter to startup without a complete configuration.\\nThis is risky as it may result in a non-functioning or insecure adapter.\\nThis should only be used when getting started.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"facebook_adapter.ts\",\n                  \"line\": 488,\n                  \"character\": 21\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"boolean\"\n              }\n            },\n            {\n              \"id\": 71,\n              \"name\": \"getAccessTokenForPage\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"comment\": {\n                \"shortText\": \"When bound to multiple teams, provide a function that, given a page id, will return the page access token for that page.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"facebook_adapter.ts\",\n                  \"line\": 481,\n                  \"character\": 25\n                }\n              ],\n              \"type\": {\n                \"type\": \"reflection\",\n                \"declaration\": {\n                  \"id\": 72,\n                  \"name\": \"__type\",\n                  \"kind\": 65536,\n                  \"kindString\": \"Type literal\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"signatures\": [\n                    {\n                      \"id\": 73,\n                      \"name\": \"__call\",\n                      \"kind\": 4096,\n                      \"kindString\": \"Call signature\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"parameters\": [\n                        {\n                          \"id\": 74,\n                          \"name\": \"pageId\",\n                          \"kind\": 32768,\n                          \"kindString\": \"Parameter\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"type\": {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        }\n                      ],\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"intrinsic\",\n                            \"name\": \"string\"\n                          }\n                        ],\n                        \"name\": \"Promise\"\n                      }\n                    }\n                  ],\n                  \"sources\": [\n                    {\n                      \"fileName\": \"facebook_adapter.ts\",\n                      \"line\": 481,\n                      \"character\": 27\n                    }\n                  ]\n                }\n              }\n            },\n            {\n              \"id\": 68,\n              \"name\": \"verify_token\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"The \\\"verify token\\\" used to initially create and verify the Webhooks subscription settings on Facebook's developer portal.\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"facebook_adapter.ts\",\n                  \"line\": 466,\n                  \"character\": 16\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            }\n          ]\n        }\n      ]\n    },\n    {\n      \"name\": \"Botkit CMS Plugin\",\n      \"packageName\": \"botkit-plugin-cms\",\n      \"path\": \"reference/cms.md\",\n      \"classes\": [\n        {\n          \"id\": 2,\n          \"name\": \"BotkitCMSHelper\",\n          \"kind\": 128,\n          \"kindString\": \"Class\",\n          \"flags\": {\n            \"isExported\": true,\n            \"isExternal\": true\n          },\n          \"comment\": {\n            \"shortText\": \"A plugin for Botkit that provides access to an instance of [Botkit CMS](https://github.com/howdyai/botkit-cms), including the ability to load script content into a DialogSet\\nand bind before, after and onChange handlers to those dynamically imported dialogs by name.\",\n            \"text\": \"```javascript\\ncontroller.use(new BotkitCMSHelper({\\n     uri: process.env.CMS_URI,\\n     token: process.env.CMS_TOKEN\\n}));\\n\\n// use the cms to test remote triggers\\ncontroller.on('message', async(bot, message) => {\\n  await controller.plugins.cms.testTrigger(bot, message);\\n});\\n```\\n\"\n          },\n          \"children\": [\n            {\n              \"id\": 4,\n              \"name\": \"constructor\",\n              \"kind\": 512,\n              \"kindString\": \"Constructor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 5,\n                  \"name\": \"new BotkitCMSHelper\",\n                  \"kind\": 16384,\n                  \"kindString\": \"Constructor signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 6,\n                      \"name\": \"config\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 44,\n                        \"name\": \"CMSOptions\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 2,\n                    \"name\": \"BotkitCMSHelper\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"cms.ts\",\n                  \"line\": 39,\n                  \"character\": 31\n                }\n              ]\n            },\n            {\n              \"id\": 3,\n              \"name\": \"name\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Botkit Plugin name\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"cms.ts\",\n                  \"line\": 39,\n                  \"character\": 15\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              },\n              \"defaultValue\": \"\\\"Botkit CMS\\\"\"\n            },\n            {\n              \"id\": 36,\n              \"name\": \"after\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 37,\n                  \"name\": \"after\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Bind a handler function that will fire after a given dialog ends.\\nProvides a way to use BotkitConversation.after() on dialogs loaded dynamically via the CMS api instead of being created in code.\",\n                    \"text\": \"```javascript\\ncontroller.plugins.cms.after('my_script', async(results, bot) => {\\n\\nconsole.log('my_script just ended! here are the results', results);\\n\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 38,\n                      \"name\": \"script_name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"The name of the script to bind to\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 39,\n                      \"name\": \"handler\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A handler function in the form async(results, bot) => {}\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 40,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 41,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 42,\n                                  \"name\": \"results\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"any\"\n                                  }\n                                },\n                                {\n                                  \"id\": 43,\n                                  \"name\": \"bot\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"name\": \"BotWorker\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"void\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"cms.ts\",\n                              \"line\": 316,\n                              \"character\": 46\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"cms.ts\",\n                  \"line\": 316,\n                  \"character\": 16\n                }\n              ]\n            },\n            {\n              \"id\": 17,\n              \"name\": \"before\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 18,\n                  \"name\": \"before\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Bind a handler function that will fire before a given script and thread begin.\\nProvides a way to use BotkitConversation.before() on dialogs loaded dynamically via the CMS api instead of being created in code.\",\n                    \"text\": \"```javascript\\ncontroller.cms.before('my_script','my_thread', async(convo, bot) => {\\n\\n // do stuff\\n console.log('starting my_thread as part of my_script');\\n // other stuff including convo.setVar convo.gotoThread\\n\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 19,\n                      \"name\": \"script_name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"The name of the script to bind to\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 20,\n                      \"name\": \"thread_name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"The name of a thread within the script to bind to\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 21,\n                      \"name\": \"handler\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A handler function in the form async(convo, bot) => {}\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 22,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 23,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 24,\n                                  \"name\": \"convo\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"name\": \"BotkitDialogWrapper\"\n                                  }\n                                },\n                                {\n                                  \"id\": 25,\n                                  \"name\": \"bot\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"name\": \"BotWorker\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"void\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"cms.ts\",\n                              \"line\": 267,\n                              \"character\": 68\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"cms.ts\",\n                  \"line\": 267,\n                  \"character\": 17\n                }\n              ]\n            },\n            {\n              \"id\": 7,\n              \"name\": \"init\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 8,\n                  \"name\": \"init\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Botkit plugin init function\\nAutoloads all scripts into the controller's main dialogSet.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 9,\n                      \"name\": \"botkit\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A Botkit controller object\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"cms.ts\",\n                  \"line\": 68,\n                  \"character\": 15\n                }\n              ]\n            },\n            {\n              \"id\": 10,\n              \"name\": \"loadAllScripts\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 11,\n                  \"name\": \"loadAllScripts\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Load all script content from the configured CMS instance into a DialogSet and prepare them to be used.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 12,\n                      \"name\": \"botkit\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"Botkit\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"cms.ts\",\n                  \"line\": 143,\n                  \"character\": 31\n                }\n              ]\n            },\n            {\n              \"id\": 26,\n              \"name\": \"onChange\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 27,\n                  \"name\": \"onChange\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Bind a handler function that will fire when a given variable is set within a a given script.\\nProvides a way to use BotkitConversation.onChange() on dialogs loaded dynamically via the CMS api instead of being created in code.\",\n                    \"text\": \"```javascript\\ncontroller.plugins.cms.onChange('my_script','my_variable', async(new_value, convo, bot) => {\\n\\nconsole.log('A new value got set for my_variable inside my_script: ', new_value);\\n\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 28,\n                      \"name\": \"script_name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"The name of the script to bind to\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 29,\n                      \"name\": \"variable_name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"The name of a variable within the script to bind to\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 30,\n                      \"name\": \"handler\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A handler function in the form async(value, convo, bot) => {}\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 31,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 32,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 33,\n                                  \"name\": \"value\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"any\"\n                                  }\n                                },\n                                {\n                                  \"id\": 34,\n                                  \"name\": \"convo\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"name\": \"BotkitDialogWrapper\"\n                                  }\n                                },\n                                {\n                                  \"id\": 35,\n                                  \"name\": \"bot\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"name\": \"BotWorker\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"void\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"cms.ts\",\n                              \"line\": 292,\n                              \"character\": 72\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"cms.ts\",\n                  \"line\": 292,\n                  \"character\": 19\n                }\n              ]\n            },\n            {\n              \"id\": 13,\n              \"name\": \"testTrigger\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 14,\n                  \"name\": \"testTrigger\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Uses the Botkit CMS trigger API to test an incoming message against a list of predefined triggers.\\nIf a trigger is matched, the appropriate dialog will begin immediately.\",\n                    \"returns\": \"Returns false if a dialog is NOT triggered, otherwise returns void.\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 15,\n                      \"name\": \"bot\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"The current bot worker instance\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"BotWorker\"\n                      }\n                    },\n                    {\n                      \"id\": 16,\n                      \"name\": \"message\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An incoming message to be interpretted\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"BotkitMessage\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"cms.ts\",\n                  \"line\": 241,\n                  \"character\": 28\n                }\n              ]\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Constructors\",\n              \"kind\": 512,\n              \"children\": [\n                4\n              ]\n            },\n            {\n              \"title\": \"Properties\",\n              \"kind\": 1024,\n              \"children\": [\n                3\n              ]\n            },\n            {\n              \"title\": \"Methods\",\n              \"kind\": 2048,\n              \"children\": [\n                36,\n                17,\n                7,\n                10,\n                26,\n                13\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"cms.ts\",\n              \"line\": 32,\n              \"character\": 28\n            }\n          ],\n          \"props\": [\n            {\n              \"id\": 3,\n              \"name\": \"name\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"comment\": {\n                \"shortText\": \"Botkit Plugin name\"\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"cms.ts\",\n                  \"line\": 39,\n                  \"character\": 15\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              },\n              \"defaultValue\": \"\\\"Botkit CMS\\\"\"\n            }\n          ],\n          \"methods\": [\n            {\n              \"id\": 36,\n              \"name\": \"after\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 37,\n                  \"name\": \"after\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Bind a handler function that will fire after a given dialog ends.\\nProvides a way to use BotkitConversation.after() on dialogs loaded dynamically via the CMS api instead of being created in code.\",\n                    \"text\": \"```javascript\\ncontroller.plugins.cms.after('my_script', async(results, bot) => {\\n\\nconsole.log('my_script just ended! here are the results', results);\\n\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 38,\n                      \"name\": \"script_name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"The name of the script to bind to\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 39,\n                      \"name\": \"handler\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A handler function in the form async(results, bot) => {}\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 40,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 41,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 42,\n                                  \"name\": \"results\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"any\"\n                                  }\n                                },\n                                {\n                                  \"id\": 43,\n                                  \"name\": \"bot\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"name\": \"BotWorker\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"void\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"cms.ts\",\n                              \"line\": 316,\n                              \"character\": 46\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"cms.ts\",\n                  \"line\": 316,\n                  \"character\": 16\n                }\n              ]\n            },\n            {\n              \"id\": 17,\n              \"name\": \"before\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 18,\n                  \"name\": \"before\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Bind a handler function that will fire before a given script and thread begin.\\nProvides a way to use BotkitConversation.before() on dialogs loaded dynamically via the CMS api instead of being created in code.\",\n                    \"text\": \"```javascript\\ncontroller.cms.before('my_script','my_thread', async(convo, bot) => {\\n\\n // do stuff\\n console.log('starting my_thread as part of my_script');\\n // other stuff including convo.setVar convo.gotoThread\\n\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 19,\n                      \"name\": \"script_name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"The name of the script to bind to\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 20,\n                      \"name\": \"thread_name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"The name of a thread within the script to bind to\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 21,\n                      \"name\": \"handler\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A handler function in the form async(convo, bot) => {}\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 22,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 23,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 24,\n                                  \"name\": \"convo\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"name\": \"BotkitDialogWrapper\"\n                                  }\n                                },\n                                {\n                                  \"id\": 25,\n                                  \"name\": \"bot\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"name\": \"BotWorker\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"void\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"cms.ts\",\n                              \"line\": 267,\n                              \"character\": 68\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"cms.ts\",\n                  \"line\": 267,\n                  \"character\": 17\n                }\n              ]\n            },\n            {\n              \"id\": 7,\n              \"name\": \"init\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 8,\n                  \"name\": \"init\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Botkit plugin init function\\nAutoloads all scripts into the controller's main dialogSet.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 9,\n                      \"name\": \"botkit\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A Botkit controller object\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"cms.ts\",\n                  \"line\": 68,\n                  \"character\": 15\n                }\n              ]\n            },\n            {\n              \"id\": 10,\n              \"name\": \"loadAllScripts\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 11,\n                  \"name\": \"loadAllScripts\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Load all script content from the configured CMS instance into a DialogSet and prepare them to be used.\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 12,\n                      \"name\": \"botkit\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"Botkit\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"void\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"cms.ts\",\n                  \"line\": 143,\n                  \"character\": 31\n                }\n              ]\n            },\n            {\n              \"id\": 26,\n              \"name\": \"onChange\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 27,\n                  \"name\": \"onChange\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Bind a handler function that will fire when a given variable is set within a a given script.\\nProvides a way to use BotkitConversation.onChange() on dialogs loaded dynamically via the CMS api instead of being created in code.\",\n                    \"text\": \"```javascript\\ncontroller.plugins.cms.onChange('my_script','my_variable', async(new_value, convo, bot) => {\\n\\nconsole.log('A new value got set for my_variable inside my_script: ', new_value);\\n\\n});\\n```\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 28,\n                      \"name\": \"script_name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"The name of the script to bind to\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 29,\n                      \"name\": \"variable_name\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"The name of a variable within the script to bind to\"\n                      },\n                      \"type\": {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"string\"\n                      }\n                    },\n                    {\n                      \"id\": 30,\n                      \"name\": \"handler\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"A handler function in the form async(value, convo, bot) => {}\\n\"\n                      },\n                      \"type\": {\n                        \"type\": \"reflection\",\n                        \"declaration\": {\n                          \"id\": 31,\n                          \"name\": \"__type\",\n                          \"kind\": 65536,\n                          \"kindString\": \"Type literal\",\n                          \"flags\": {\n                            \"isExported\": true\n                          },\n                          \"signatures\": [\n                            {\n                              \"id\": 32,\n                              \"name\": \"__call\",\n                              \"kind\": 4096,\n                              \"kindString\": \"Call signature\",\n                              \"flags\": {\n                                \"isExported\": true\n                              },\n                              \"parameters\": [\n                                {\n                                  \"id\": 33,\n                                  \"name\": \"value\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"any\"\n                                  }\n                                },\n                                {\n                                  \"id\": 34,\n                                  \"name\": \"convo\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"name\": \"BotkitDialogWrapper\"\n                                  }\n                                },\n                                {\n                                  \"id\": 35,\n                                  \"name\": \"bot\",\n                                  \"kind\": 32768,\n                                  \"kindString\": \"Parameter\",\n                                  \"flags\": {\n                                    \"isExported\": true\n                                  },\n                                  \"type\": {\n                                    \"type\": \"reference\",\n                                    \"name\": \"BotWorker\"\n                                  }\n                                }\n                              ],\n                              \"type\": {\n                                \"type\": \"reference\",\n                                \"typeArguments\": [\n                                  {\n                                    \"type\": \"intrinsic\",\n                                    \"name\": \"void\"\n                                  }\n                                ],\n                                \"name\": \"Promise\"\n                              }\n                            }\n                          ],\n                          \"sources\": [\n                            {\n                              \"fileName\": \"cms.ts\",\n                              \"line\": 292,\n                              \"character\": 72\n                            }\n                          ]\n                        }\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"intrinsic\",\n                    \"name\": \"void\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"cms.ts\",\n                  \"line\": 292,\n                  \"character\": 19\n                }\n              ]\n            },\n            {\n              \"id\": 13,\n              \"name\": \"testTrigger\",\n              \"kind\": 2048,\n              \"kindString\": \"Method\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 14,\n                  \"name\": \"testTrigger\",\n                  \"kind\": 4096,\n                  \"kindString\": \"Call signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"comment\": {\n                    \"shortText\": \"Uses the Botkit CMS trigger API to test an incoming message against a list of predefined triggers.\\nIf a trigger is matched, the appropriate dialog will begin immediately.\",\n                    \"returns\": \"Returns false if a dialog is NOT triggered, otherwise returns void.\\n\"\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 15,\n                      \"name\": \"bot\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"The current bot worker instance\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"name\": \"BotWorker\"\n                      }\n                    },\n                    {\n                      \"id\": 16,\n                      \"name\": \"message\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"comment\": {\n                        \"text\": \"An incoming message to be interpretted\"\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"typeArguments\": [\n                          {\n                            \"type\": \"reference\",\n                            \"name\": \"BotkitMessage\"\n                          }\n                        ],\n                        \"name\": \"Partial\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"typeArguments\": [\n                      {\n                        \"type\": \"intrinsic\",\n                        \"name\": \"any\"\n                      }\n                    ],\n                    \"name\": \"Promise\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"cms.ts\",\n                  \"line\": 241,\n                  \"character\": 28\n                }\n              ]\n            }\n          ],\n          \"constructors\": [\n            {\n              \"id\": 4,\n              \"name\": \"constructor\",\n              \"kind\": 512,\n              \"kindString\": \"Constructor\",\n              \"flags\": {\n                \"isPublic\": true,\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"signatures\": [\n                {\n                  \"id\": 5,\n                  \"name\": \"new BotkitCMSHelper\",\n                  \"kind\": 16384,\n                  \"kindString\": \"Constructor signature\",\n                  \"flags\": {\n                    \"isExported\": true\n                  },\n                  \"parameters\": [\n                    {\n                      \"id\": 6,\n                      \"name\": \"config\",\n                      \"kind\": 32768,\n                      \"kindString\": \"Parameter\",\n                      \"flags\": {\n                        \"isExported\": true\n                      },\n                      \"type\": {\n                        \"type\": \"reference\",\n                        \"id\": 44,\n                        \"name\": \"CMSOptions\"\n                      }\n                    }\n                  ],\n                  \"type\": {\n                    \"type\": \"reference\",\n                    \"id\": 2,\n                    \"name\": \"BotkitCMSHelper\"\n                  }\n                }\n              ],\n              \"sources\": [\n                {\n                  \"fileName\": \"cms.ts\",\n                  \"line\": 39,\n                  \"character\": 31\n                }\n              ]\n            }\n          ]\n        }\n      ],\n      \"interfaces\": [\n        {\n          \"id\": 44,\n          \"name\": \"CMSOptions\",\n          \"kind\": 256,\n          \"kindString\": \"Interface\",\n          \"flags\": {\n            \"isExported\": true,\n            \"isExternal\": true\n          },\n          \"children\": [\n            {\n              \"id\": 47,\n              \"name\": \"controller\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"cms.ts\",\n                  \"line\": 329,\n                  \"character\": 14\n                }\n              ],\n              \"type\": {\n                \"type\": \"reference\",\n                \"name\": \"Botkit\"\n              }\n            },\n            {\n              \"id\": 46,\n              \"name\": \"token\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"cms.ts\",\n                  \"line\": 328,\n                  \"character\": 9\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 45,\n              \"name\": \"uri\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"cms.ts\",\n                  \"line\": 327,\n                  \"character\": 7\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            }\n          ],\n          \"groups\": [\n            {\n              \"title\": \"Properties\",\n              \"kind\": 1024,\n              \"children\": [\n                47,\n                46,\n                45\n              ]\n            }\n          ],\n          \"sources\": [\n            {\n              \"fileName\": \"cms.ts\",\n              \"line\": 326,\n              \"character\": 27\n            }\n          ],\n          \"props\": [\n            {\n              \"id\": 47,\n              \"name\": \"controller\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true,\n                \"isOptional\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"cms.ts\",\n                  \"line\": 329,\n                  \"character\": 14\n                }\n              ],\n              \"type\": {\n                \"type\": \"reference\",\n                \"name\": \"Botkit\"\n              }\n            },\n            {\n              \"id\": 46,\n              \"name\": \"token\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"cms.ts\",\n                  \"line\": 328,\n                  \"character\": 9\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            },\n            {\n              \"id\": 45,\n              \"name\": \"uri\",\n              \"kind\": 1024,\n              \"kindString\": \"Property\",\n              \"flags\": {\n                \"isExported\": true,\n                \"isExternal\": true\n              },\n              \"sources\": [\n                {\n                  \"fileName\": \"cms.ts\",\n                  \"line\": 327,\n                  \"character\": 7\n                }\n              ],\n              \"type\": {\n                \"type\": \"intrinsic\",\n                \"name\": \"string\"\n              }\n            }\n          ]\n        }\n      ]\n    }\n  ],\n  \"adapters\": [\n    {\n      \"name\": \"Websocket and Webhooks\",\n      \"path\": \"platforms/web.md\"\n    },\n    {\n      \"name\": \"Webex Teams\",\n      \"path\": \"platforms/webex.md\"\n    },\n    {\n      \"name\": \"Slack\",\n      \"path\": \"platforms/slack.md\"\n    },\n    {\n      \"name\": \"Google Hangouts\",\n      \"path\": \"platforms/hangouts.md\"\n    },\n    {\n      \"name\": \"Twilio SMS\",\n      \"path\": \"platforms/twilio-sms.md\"\n    },\n    {\n      \"name\": \"Facebook Messenger\",\n      \"path\": \"platforms/facebook.md\"\n    }\n  ],\n  \"plugins\": [\n    {\n      \"name\": \"Botkit CMS Plugin\",\n      \"path\": \"plugins/cms.md\"\n    }\n  ]\n}"
  },
  {
    "path": "packages/docs/index.md",
    "content": "# Botkit: Building Blocks for Building Bots\n\n<a href=\"https://www.npmjs.com/package/botkit\" title=\"View most recent version on npm\"><img src=\"https://img.shields.io/npm/v/botkit.svg\" aria-hidden=\"true\" alt=\"npm version badge\"></a>\n<a href=\"https://david-dm.org/howdyai/botkit\" title=\"View status of dependencies\"><img src=\"https://img.shields.io/david/howdyai/botkit.svg\" alt=\"Dependency status badge\" aria-hidden=\"true\"></a>\n<a href=\"https://spdx.org/licenses/MIT\" title=\"View MIT License\"><img src=\"https://img.shields.io/npm/l/botkit.svg\" alt=\"MIT License Badge\" aria-hidden=\"true\"></a>\n\n--------------------------------------------------------------------------------\n\n**Botkit is an open source developer tool for building chat bots, apps and custom integrations for major messaging platforms.**\n\n## Install Botkit\n\n### Remix on Glitch\n\nWant to dive right in? [Remix one of our starter kits on Glitch](https://glitch.com/botkit). You'll start with a fully functioning app that you can edit and run from the browser!\n\n [![Remix on Glitch](glitch.png)](https://glitch.com/botkit)\n\n\n### Command Line Interface\n\nThe best way to get started locally with Botkit is by installing our command line tool, and using it to create a new Botkit project. This will install and configure a starter kit for you!\n\n```bash\nnpm install -g yo generator-botkit\nyo botkit\n```\n\n### **Start from Scratch**\n\nYou can also add Botkit into an existing Node application.\n\nFirst, add it to your project:\n\n```bash\nnpm install --save botkit\n```\n\nThen, add Botkit to your application code:\n\n```javascript\nlet { Botkit } = require('botkit');\n\nconst controller = new Botkit(MY_CONFIGURATION);\n\ncontroller.hears('hello','direct_message', function(bot, message) {\n    bot.reply(message,'Hello yourself!');\n});\n```\n\n## Build Your Bot\n\nBotkit is a programming library, along with a suite of supporting tools and plugins, that provides bot builders a platform independent, language-like interface for building a chatbot or messaging app for any platform. It handles all the nitty gritty technical details, allowing you to focus on building COOL FEATURES for your bot.\n\nThe toolkit is designed to provide meaningful building blocks for creating conversational user interfaces - with functions like `hears()`, `ask()`, and `reply()` that do what they say they do.\n\n## Hearing Messages\n\nMost bots do their thing by listening for keywords, phrases or patterns in messages from users. Botkit has a special event handler called `hears()` that makes it easy to configure your bot to listen for this type of trigger.\n\n```javascript\n// listen for a message containing the word \"hello\", and send a reply\ncontroller.hears('hello','message',async(bot, message) => {\n    // do something!\n    await bot.reply(message, 'Hello human')\n});\n```\n\n[Read more about hearing things &raquo;](core.md#matching-patterns-and-keywords-with-hears)\n\n## Responding to Events\n\nBots can respond to non-verbal events as well, like when a new user joins a channel, a file gets uploaded, or a button gets clicked. These events are handled using an event handling pattern that should look familiar to most developers. Most events in Botkit can be replied to like normal messages.\n\n```javascript\n// wait for a new user to join a channel, then say hi\ncontroller.on('channel_join', async(bot, message) => {\n    await bot.reply(message,'Welcome to the channel!');\n});\n```\n\n[See a full list of events and more information about handling them &raquo;](core.md#receiving-messages-and-events)\n\n## Conversation Management\n\nBotkit has a flexible system for handling scripted dialog and transactional conversations involving questions, branching logic, and other dynamic behaviors.\n\n[Read about Conversations &raquo;](core.md#using-dialogs)\n\n\n## Extend Botkit with Middleware\n\nIn addition to taking direct action in response to a certain message or type of event, Botkit can also take passive action on messages as they move through the application using middlewares. Middleware functions work by changing messages, adding new fields, firing alternate events, and modifying or overriding the behavior of Botkit's core features.\n\nMiddleware can be used to adjust how Botkit receives, processes, and sends messages. [Here is a list of available middleware endpoints](core.md#middlewares).\n\n```javascript\n// Log every message received\ncontroller.middleware.receive.use(function(bot, message, next) {\n\n    // log it\n    console.log('RECEIVED: ', message);\n\n    // modify the message\n    message.logged = true;\n\n    // continue processing the message\n    next();\n\n});\n\n// Log every message sent\ncontroller.middleware.send.use(function(bot, message, next) {\n\n    // log it\n    console.log('SENT: ', message);\n\n    // modify the message\n    message.logged = true;\n\n    // continue processing the message\n    next();\n\n});\n```\n\n\n## What's Next?\n\n* [Continue learning about Botkit's core features](core.md)\n* [View set-up guides for all the major platforms](provisioning/index.md)\n"
  },
  {
    "path": "packages/docs/package.json",
    "content": "{\n  \"name\": \"botkit-docs\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Documentation for Botkit 4.x\",\n  \"scripts\": {\n    \"build-docs\": \"./build/build.sh\"\n  },\n  \"author\": \"benbrown@gmail.com\",\n  \"license\": \"MIT\",\n  \"dependencies\": {\n    \"handlebars\": \"^4.7.7\",\n    \"typedoc\": \"^0.22.10\",\n    \"typedoc-plugin-external-module-name\": \"4.0.6\"\n  },\n  \"devDependencies\": {\n    \"typedoc-plugin-no-inherit\": \"^1.1.10\"\n  }\n}\n"
  },
  {
    "path": "packages/docs/platforms/facebook.md",
    "content": "[&larr; Botkit Documentation](../core.md)  [&larr; Platform Index](index.md) \n\n# botbuilder-adapter-facebook\nConnect [Botkit](https://www.npmjs.com/package/botkit) or [BotBuilder](https://www.npmjs.com/package/botbuilder) to Facebook Messenger.\n\nThis package contains an adapter that communicates directly with the Facebook Messenger API,\nand translates messages to and from a standard format used by your bot. This package can be used alongside your favorite bot development framework to build bots that work with Facebook Messenger.\n\n## Install Package\n\nAdd this package to your project using npm:\n\n```bash\nnpm install --save botbuilder-adapter-facebook\n```\n\nImport the adapter class into your code:\n\n```javascript\nconst { FacebookAdapter } = require('botbuilder-adapter-facebook');\n```\n\n## Get Started\n\nIf you are starting a brand new project, [follow these instructions to create a customized application template.](../index.md)\n\n## Use FacebookAdapter in your App\n\nFacebookAdapter provides a translation layer for Botkit and BotBuilder so that bot developers can connect to Facebook Messenger and have access to Facebook's API.\n\n### Botkit Basics\n\nWhen used in concert with Botkit, developers need only pass the configured adapter to the Botkit constructor, as seen below. Botkit will automatically create and configure the webhook endpoints and other options necessary for communicating with Facebook.\n\nDevelopers can then bind to Botkit's event emitting system using `controller.on` and `controller.hears` to filter and handle incoming events from the messaging platform. [Learn more about Botkit's core feature &rarr;](../index.md).\n\n[A full description of the FacebookAdapter options and example code can be found in the class reference docs.](../reference/facebook.md#create-a-new-facebookadapter)\n\n```javascript\nconst adapter = new FacebookAdapter({\n     verify_token: process.env.FACEBOOK_VERIFY_TOKEN,\n     app_secret: process.env.FACEBOOK_APP_SECRET,\n     access_token: process.env.FACEBOOK_ACCESS_TOKEN\n});\n\nadapter.use(new FacebookEventTypeMiddleware());\n\nconst controller = new Botkit({\n    adapter,\n    // ...other options\n});\n\ncontroller.on('message', async(bot, message) => {\n    await bot.reply(message, 'I heard a message!');\n});\n```\n\n### BotBuilder Basics\n\nAlternately, developers may choose to use `FacebookAdapter` with BotBuilder. With BotBuilder, the adapter is used more directly with a webserver, and all incoming events are handled as [Activities](https://docs.microsoft.com/en-us/javascript/api/botframework-schema/activity?view=botbuilder-ts-latest).\n\n```javascript\nconst { FacebookAdapter } = require('botbuilder-adapter-facebook');\nconst restify = require('restify');\n\nconst adapter = new FacebookAdapter({\n     verify_token: process.env.FACEBOOK_VERIFY_TOKEN,\n     app_secret: process.env.FACEBOOK_APP_SECRET,\n     access_token: process.env.FACEBOOK_ACCESS_TOKEN\n});\nconst server = restify.createServer();\nserver.use(restify.plugins.bodyParser());\nserver.use(restify.plugins.queryParser());\n\nserver.get('/api/messages', (req, res) => {\n     if (req.query['hub.mode'] === 'subscribe') {\n          if (req.query['hub.verify_token'] === process.env.FACEBOOK_VERIFY_TOKEN) {\n               const val = req.query['hub.challenge'];\n               res.sendRaw(200, val);\n          } else {\n               console.log('failed to verify endpoint');\n               res.send('OK');\n          }\n     }\n});\n\nserver.post('/api/messages', (req, res) => {\n     adapter.processActivity(req, res, async(context) => {\n         await context.sendActivity('I heard a message!');\n     });\n});\n\nserver.listen(process.env.port || process.env.PORT || 3000, () => {\n     console.log(`\\n${ server.name } listening to ${ server.url }`);\n });\n```\n\n### Multi-page Support\n\nIn the examples above, the `FacebookAdapter` constructor received a single `access_token` parameters. This binds the adapter and all API calls it makes to a single Facebook page.\n\nTo use `FacebookAdapter` with multiple Facebook pages, the constructor must receive a function as a paramter named `getAccessTokenForPage` that is responsible for returning a token value when provided a Facebook page ID. The application must implement its own mechanism for securely storing and retrieving the token.\n\n```javascript\nconst adapter = new FacebookAdapter({\n    verify_token: process.env.FACEBOOK_VERIFY_TOKEN,\n    app_secret: process.env.FACEBOOK_APP_SECRET,\n    getAccessTokenForPage: async(pageId) => { \n        // do something to fetch the page access token for pageId.\n        return token;\n    }\n});\n```\n\n## Class Reference\n\n* [FacebookAdapter](../reference/facebook.md#facebookadapter)\n* [BotWorker Extensions](../reference/facebook.md#facebookbotworker)\n* [Facebook API Client](../reference/facebook.md#facebookapi)\n\n## Event List\n\n[Botkit event types are controlled by the FacebookEventMiddleware](../reference/facebook.md#facebookeventtypemiddleware).\n\nWithout this middleware applied, Botkit bots will receive `message` events when a user types a message or clicks a postback_button, and an `event` event for all other types of event received from Facebook.\n\nMost Botkit developers who plan to use features above and beyond Facebook's send API should enable this middleware.\n\n## Calling Facebook APIs\n\nThis package also includes [a minimal Facebook API client](../reference/facebook.md#facebookapi) for developers who want to use one of the many available API endpoints.\n\nIn Botkit handlers, the `bot` worker object passed into all handlers will contain a `bot.api` field that contains the client, preconfigured and ready to use.\n\nTo use with a BotBuilder application, the adapter provides the [getAPI() method](../reference/facebook.md#getapi).\n\n```javascript\ncontroller.on('message', async(bot, message) {\n\n    // call the facebook API to get the bot's page identity\n    let identity = await bot.api.callAPI('/me', 'GET', {});\n    await bot.reply(message,`My name is ${ identity.name }`);\n\n});\n```\n\n## Botkit Extensions\n\nIn Botkit handlers, the `bot` worker for Facebook contains [all of the base methods](../reference/core.md#BotWorker) as well as the following platform-specific extensions:\n\n### Use attachments, quick replies and other rich message features\n\nBotkit will automatically construct your outgoing messages according to Facebook's specifications. To use attachments, quick replies or other features, add them to the message object used to create the reply:\n\n```javascript\nawait bot.reply(message, {\n    text: 'Choose a button', \n    quick_replies: [\n        {\n            \"content_type\":\"text\",\n            \"title\":\"Foo\",\n            \"payload\":\"true\"\n        },\n        {\n            \"content_type\":\"text\",\n            \"title\":\"Bar\",\n            \"payload\":\"false\"\n        }\n    ]\n});\n```\n\n### [Spawn a worker for a specific page](../reference/facebook.md#create-a-new-facebookbotworker)\n\nFor a bot that works with multiple pages, it is possible to spawn bot workers bound to a specific page by passing the page ID as the primary parameter to `controller.spawn()`:\n\n```javascript\nlet bot = await controller.spawn(FACEBOOK_PAGE_ID);\n```\n\n### [bot.startConversationWithUser()](../reference/facebook.md#startconversationwithuser)\n\nUse this method to initiate a conversation with a user. After calling this method, any further actions carried out by the bot worker will happen with the specified user.\n\nThis can be used to create or resume conversations with users that are not in direct response to an incoming message, like those sent on a schedule or in response to external events.\n\n## Community & Support\n\nJoin our thriving community of Botkit developers and bot enthusiasts at large.\nOver 10,000 members strong, [our open Slack group](https://community.botkit.ai) is\n_the place_ for people interested in the art and science of making bots.\nCome to ask questions, share your progress, and commune with your peers!\n\nYou can also find help from members of the Botkit team [in our dedicated Cisco Spark room](https://eurl.io/#SyNZuomKx)!\n\n## About Botkit\n\nBotkit is a part of the [Microsoft Bot Framework](https://dev.botframework.com).\n\nWant to contribute? [Read the contributor guide](https://github.com/howdyai/botkit/blob/master/CONTRIBUTING.md)\n\nBotkit is released under the [MIT Open Source license](https://github.com/howdyai/botkit/blob/master/LICENSE.md)\n\n"
  },
  {
    "path": "packages/docs/platforms/hangouts.md",
    "content": "[&larr; Botkit Documentation](../core.md)  [&larr; Platform Index](index.md) \n\n# botbuilder-adapter-hangouts\n\nConnect [Botkit](https://www.npmjs.com/package/botkit) or [BotBuilder](https://www.npmjs.com/package/botbuilder) to Google Hangouts.\n\nThis package contains an adapter that communicates directly with the Google Hangouts API,\nand translates messages to and from a standard format used by your bot. This package can be used alongside your favorite bot development framework to build bots that work with Google Hangouts.\n\n## Install Package\n\nAdd this package to your project using npm:\n\n```bash\nnpm install --save botbuilder-adapter-hangouts\n```\n\nImport the adapter class into your code:\n\n```javascript\nconst { HangoutsAdapter } = require('botbuilder-adapter-hangouts');\n```\n\n## Get Started\n\nIf you are starting a brand new project, [follow these instructions to create a customized application template.](../index.md)\n\n## Use HangoutsAdapter in your App\n\nHangoutsAdapter provides a translation layer for Botkit and BotBuilder so that bot developers can connect to Google Hangouts and have access to the Google Hangouts's API.\n\n### Botkit Basics\n\nWhen used in concert with Botkit, developers need only pass the configured adapter to the Botkit constructor, as seen below. Botkit will automatically create and configure the webhook endpoints and other options necessary for communicating with Google.\n\nDevelopers can then bind to Botkit's event emitting system using `controller.on` and `controller.hears` to filter and handle incoming events from the messaging platform. [Learn more about Botkit's core feature &rarr;](../index.md).\n\n[A full description of the HangoutsAdapter options and example code can be found in the class reference docs.](../reference/hangouts.md#create-a-new-hangoutsadapter)\n\n```javascript\nconst adapter = new HangoutsAdapter({\n    token: process.env.GOOGLE_TOKEN,\n    google_auth_params: {\n        credentials: process.env.GOOGLE_CREDS\n    }\n});\n\nconst controller = new Botkit({\n    adapter,\n    // ...other options\n});\n\ncontroller.on('message', async(bot, message) => {\n    await bot.reply(message, 'I heard a message!');\n});\n```\n\n### BotBuilder Basics\n\nAlternately, developers may choose to use `HangoutsAdapter` with BotBuilder. With BotBuilder, the adapter is used more directly with a webserver, and all incoming events are handled as [Activities](https://docs.microsoft.com/en-us/javascript/api/botframework-schema/activity?view=botbuilder-ts-latest).\n\n```javascript\nconst adapter = new HangoutsAdapter({\n    token: process.env.GOOGLE_TOKEN,\n    google_auth_params: {\n        credentials: process.env.GOOGLE_CREDS\n    }\n});\n\nconst server = restify.createServer();\nserver.use(restify.plugins.bodyParser());\nserver.post('/api/messages', (req, res) => {\n     adapter.processActivity(req, res, async(context) => {\n         await context.sendActivity('I heard a message!');\n     });\n});\n```\n\n## Class Reference\n\n* [HangoutsAdapter](../reference/hangouts.md#hangoutsadapter)\n* [BotWorker Extensions](../reference/hangouts.md#hangoutsbotworker)\n\n## Event List\n\nBotkit will emit the following events: \n\n| Event | Description\n|--- |---\n| message | a message from a user received in a shared channel\n| card_clicked | a user clicked a button on a card attachment\n| direct_message | a message from a user received in a private 1:1 with the bot\n| bot_room_join | the bot joined a new room\n| bot_dm_join | a new 1:1 with a user has been created\n| bot_room_leave | the bot has been removed from a room\n| bot_dm_leave | a 1:1 with a user has been closed\n\n## Calling Google APIs\n\nThis package exposes a pre-configured Google API client for developers who want to use one of the many available API endpoints.\n\nIn Botkit handlers, the `bot` worker object passed into all handlers will contain a `bot.api` field that contains the client, preconfigured and ready to use.\n\n```javascript\ncontroller.on('message', async(bot, message) {\n\n    // get a list of the members of a room\n    let members = await bot.api.spaces.members.get({name: message.channel});\n    // .. do stuff\n\n});\n```\n\n## Botkit Extensions\n\nIn Botkit handlers, the `bot` worker for Hangouts contains [all of the base methods](../reference/core.md#BotWorker) as well as the following platform-specific extensions:\n\n### Use cards\n\nBotkit will automatically construct your outgoing messages according to Google's specifications. [Google Hangouts supports card attachments with buttons](https://developers.google.com/hangouts/chat/reference/message-formats/cards).\n\nTo use card attachments, add the `cards` field to the outgoing message object used to create the reply:\n\n```javascript\nawait bot.reply(message, {\n    text: 'Pick a card!',\n    cards: [\n        {\n            // card object\n        },\n    ]\n});\n```\n\n### Reply in a new thread\n\nIn Google Hangouts, messages are organized into threads. Botkit provides specialized methods for cases where a bot's reply should create a new thread, or for when a bot should conduct an entire conversation in new/separate thread.\n\n* [bot.replyInThread](../reference/hangouts.md#replyinthread)\n* [bot.startConversationInThread](../reference/hangouts.md#startconversationinthread)\n\n### Respond to `card_clicked` events\n\nWhen a button in an card attachment is clicked, Google sends a special event that requires a special response.  Botkit will emit a `card_clicked` event, which should be responded to using \neither `bot.replyWithUpdate()` or `bot.replyWithNew()`.\n\n[See Google doc for interactive cards &rarr;](https://developers.google.com/hangouts/chat/how-tos/cards-onclick#responding_to_clicks_with_a_new_or_updated_message).\n\n* [bot.replyWithUpdate](../reference/hangouts.md#replywithupdate)\n* [bot.replyWithNew](../reference/hangouts.md#relpywithnew)\n\n### Update and remove messages\n\nGoogle Hangouts supports updating and deleting messages. Do so with the following convenience methods:\n\n* [bot.updateMessage](../reference/hangouts.md#updatemessage)\n* [bot.deleteMessage](../reference/hangouts.md#deletemessage)\n\n\n## Community & Support\n\nJoin our thriving community of Botkit developers and bot enthusiasts at large.\nOver 10,000 members strong, [our open Slack group](https://community.botkit.ai) is\n_the place_ for people interested in the art and science of making bots.\nCome to ask questions, share your progress, and commune with your peers!\n\nYou can also find help from members of the Botkit team [in our dedicated Cisco Spark room](https://eurl.io/#SyNZuomKx)!\n\n## About Botkit\n\nBotkit is a part of the [Microsoft Bot Framework](https://dev.botframework.com).\n\nWant to contribute? [Read the contributor guide](https://github.com/howdyai/botkit/blob/master/CONTRIBUTING.md)\n\nBotkit is released under the [MIT Open Source license](https://github.com/howdyai/botkit/blob/master/LICENSE.md)\n"
  },
  {
    "path": "packages/docs/platforms/index.md",
    "content": "# Platform Adapters\n\n[&larr; Botkit Core Docs](../core.md)\n\n* [Websocket and Webhooks](../platforms/web.md)\n* [Webex Teams](../platforms/webex.md)\n* [Slack](../platforms/slack.md)\n* [Google Hangouts](../platforms/hangouts.md)\n* [Twilio SMS](../platforms/twilio-sms.md)\n* [Facebook Messenger](../platforms/facebook.md)\n* [Microsoft Teams](../core.md#using-bot-framework-channels)\n"
  },
  {
    "path": "packages/docs/platforms/slack.md",
    "content": "[&larr; Botkit Documentation](../core.md)  [&larr; Platform Index](index.md) \n\n# botbuilder-adapter-slack\n\nConnect [Botkit](https://www.npmjs.com/package/botkit) or [BotBuilder](https://www.npmjs.com/package/botbuilder) to Slack.\n\nThis package contains an adapter that communicates directly with the Slack API,\nand translates messages to and from a standard format used by your bot. This package can be used alongside your favorite bot development framework to build bots that work with Slack.\n\n## Install Package\n\nAdd this package to your project using npm:\n\n```bash\nnpm install --save botbuilder-adapter-slack\n```\n\nImport the adapter class into your code:\n\n```javascript\nconst { SlackAdapter } = require('botbuilder-adapter-slack');\n```\n\n## Get Started\n\nIf you are starting a brand new project, [follow these instructions to create a customized application template.](../index.md)\n\n## Use SlackAdapter in your App\n\nSlackAdapter provides a translation layer for Botkit and BotBuilder so that bot developers can connect to Slack and have access to the Slack's API.\n\n### Botkit Basics\n\nWhen used in concert with Botkit, developers need only pass the configured adapter to the Botkit constructor, as seen below. Botkit will automatically create and configure the webhook endpoints and other options necessary for communicating with Slack.\n\nDevelopers can then bind to Botkit's event emitting system using `controller.on` and `controller.hears` to filter and handle incoming events from the messaging platform. [Learn more about Botkit's core feature &rarr;](../index.md).\n\n[A full description of the SlackAdapter options and example code can be found in the class reference docs.](../reference/slack.md#create-a-new-slackadapter)\n\n```javascript\nconst adapter = new SlackAdapter({\n    clientSigningSecret: process.env.SLACK_SECRET,\n    botToken: process.env.SLACK_TOKEN\n});\n\nconst controller = new Botkit({\n    adapter,\n    // ...other options\n});\n\ncontroller.on('message', async(bot, message) => {\n    await bot.reply(message, 'I heard a message!');\n});\n```\n\n### BotBuilder Basics\n\nAlternately, developers may choose to use `SlackAdapter` with BotBuilder. With BotBuilder, the adapter is used more directly with a webserver, and all incoming events are handled as [Activities](https://docs.microsoft.com/en-us/javascript/api/botframework-schema/activity?view=botbuilder-ts-latest).\n\n```javascript\nconst adapter = new SlackAdapter({\n    clientSigningSecret: process.env.SLACK_SECRET,\n    botToken: process.env.SLACK_TOKEN\n});\n\nconst server = restify.createServer();\nserver.use(restify.plugins.bodyParser());\nserver.post('/api/messages', (req, res) => {\n     adapter.processActivity(req, res, async(context) => {\n         await context.sendActivity('I heard a message!');\n     });\n});\n```\n\n### Important URLs\n\nYour bot application will present several important URLs. You'll need to configure your Slack application profile with these urls.\n\nThe messaging endpoint, which receives all events from Slack is: `https://YOURBOT/api/messages`\n\nThe default \"install\" URL that triggers the oauth flow for multi-team installation is `https://YOURBOT/install`\n\nThe oauth callback URL (or \"redirect uri\") that should be added to your Slack application profile is `https://YOURBOT/install/auth`\n\n### Multi-team Support\n\nIn the examples above, the `SlackAdapter` constructor received a single `botToken` parameters. This binds the adapter and all API calls it makes to a single Slack workspace.\n\nTo use `SlackAdapter` with multiple Slack workspaces, the constructor must receive a a different set of parameters. These parameters allow the adapter to be configured to work as an oauth client application of Slack's API, and will expose an \"install link\" used to add the application to each Slack workspace.\n\nIn additionto fields related to oauth, the constructor must also receive 2 functions:\n\n* a parameter named `getTokenForTeam` that is responsible for returning a token value when provided a Slack workspace ID.\n* a parameter named `getBotUserByTeam` that is responsible for returning a bot's user id value when provided a Slack workspace ID.\n\nThe application must implement its own mechanism for securely storing and retrieving these values.\n\n```javascript\nconst adapter = new SlackAdapter({\n    clientSigningSecret: process.env.SLACK_SECRET,\n    clientId: process.env.CLIENT_ID, // oauth client id\n    clientSecret: process.env.CLIENT_SECRET, // oauth client secret\n    scopes: ['bot'], // oauth scopes requested, 'bot' deprecated by Slack in favor of granular permissions\n    redirectUri: process.env.REDIRECT_URI, // url to redirect post-login\n    oauthVersion: 'v1', // or use v2\n    getTokenForTeam: async(team_id) => {\n        // load the token for this team\n        // as captured during oauth \n    }, \n    getBotUserByTeam: async(team_id) = {\n        // load bot user id for this team   \n        // as captured during oauth \n    }\n});\n\n// Create a route for the install link.\n// This will redirect the user to Slack's permission request page.\ncontroller.webserver.get('/install', (req, res) => {\n    res.redirect(adapter.getInstallLink());\n});\n\n// Create a route to capture the results of the oauth flow.\n// this URL should match the value of the `redirectUri` passed to Botkit.\ncontroller.webserver.get('/install/auth', (req, res) => {\n    try {\n        const results = await controller.adapter.validateOauthCode(req.query.code);\n\n        // Store token by team in bot state.\n        let team = results.team_id; // results.team.id in oauth v2\n        let token = results.bot.bot_access_token; // results.access_token in oauth v2\n        let userId = results.bot.bot_user_id; // results.bot_user_id in oauth v2\n\n        // Securely store the token and usedId so that they can be retrieved later by the team id.\n        // ...\n\n        // customize your post-install success page\n        res.send('Success! Bot installed.');\n\n    } catch (err) {\n        console.error('OAUTH ERROR:', err);\n        // customize your post-install failure page\n        res.status(401);\n        res.send(err.message);\n    }\n});\n```\n\n### Using Slack's v2 OAuth\n\nTo use Slack's [newer \"granular scopes\"](https://api.slack.com/authentication/oauth-v2), specify `oauthVersion: 'v2'` in your adapter configuration.\nThis will cause the adapter to use the v2 oauth URL and credential validation function.\nHowever, note that the payload returned `validateOauthCode` differs between versions.\n\nIn v1, your bot's token will be located at `results.bot.bot_access_token`, whereas in v2, it will be `results.access_token`.\n\nIn v1, your bot's user id will be at `results.bot.bot_user_id`, whereas in v2 it will be `results.bot_user_id`.\n\nFrom Slack's official docs:\n\n* [V1 response payload](https://api.slack.com/methods/oauth.access#response)\n* [V2 response payload](https://api.slack.com/methods/oauth.v2.access#response)\n\nTake care to update your auth handler function when you migrate to granular scopes.\n\n## Class Reference\n\n* [SlackAdapter](../reference/slack.md#slackadapter)\n* [BotWorker Extensions](../reference/slack.md#slackbotworker)\n* [SlackMessageTypeMiddleware](../reference/slack.md#slackmessagetypemiddleware)\n* [SlackEventMiddleware](../reference/slack.md#slackeventmiddleware)\n\n\n## Event List\n\nBotkit will emit the following events: \n\n| Event | Description\n|--- |---\n| message | a message from a user received in a shared channel\n| event | all other events from Slack (unless middlewares enabled, see below)\n\nThis package includea a set of optional middleware that will modify the type of incoming events to match their Slack event types (rather than being cast into generic \"message or \"event\" types).\n\nMost Botkit developers who plan to use features above and beyond the basic send/receive API should enable these middleware.\n\nImport the adapter and the middlewares:\n\n```javascript\n// load SlackAdapter AND SlackEventMiddleware\nconst { SlackAdapter, SlackEventMiddleware, SlackMessageTypeMiddleware } = require('botbuilder-adapter-slack');\n```\n\nCreate your adapter (as above), then bind the middlewares to the adapter:\n\n```javascript\nadapter.use(new SlackEventMiddleware());\nadapter.use(new SlackMessageTypeMiddleware());\n```\n\nNow, Botkit will emit events with their original Slack names:\n\n```\ncontroller.on('channel_join', async(bot, message) => {\n    // do stuff\n});\n```\n\n## Calling Slack APIs\n\nThis package exposes a pre-configured [Slack API client](https://slack.dev/node-slack-sdk/web-api) for developers who want to use one of the many available API endpoints.\n\nIn Botkit handlers, the `bot` worker object passed into all handlers will contain a `bot.api` field that contains the client, preconfigured and ready to use.\n\n```javascript\ncontroller.on('message', async(bot, message) {\n\n    // load a user profile\n    let profile = await bot.api.users.info({user: message.user});\n\n});\n```\n\n## Botkit Extensions\n\nIn Botkit handlers, the `bot` worker for Slack contains [all of the base methods](../reference/core.md#BotWorker) as well as the following platform-specific extensions:\n\n### [controller.getInstallLink()](../reference/slack.md#getinstalllink)\n\nReturns the first step of an oauth-flow that results in the Botkit application being enabled on a workspace.\nUse this in concert with [multi-team support](#multi-team-support).\n\n### [controller.validateOauthCode()](../reference/slack.md#validateoauthcode)\n\nThis method receives the oauth code returned by Slack at the end of the oauth-flow and returns all of the credentials and authentication details associated with it.  Use this to capture the workspace token and bot user ID needed for multi-team support.\n\n### Use attachments, blocks, and other rich message features\n\nBotkit will automatically construct your outgoing messages according to Slack's specifications. To use attachments, blocks or other features, add them to the message object used to create the reply.\n\n**Use Block Kit Blocks**\n\nThe preferred way of composing interactive messages is using Slack's Block Kit.  [Read the official Slack documentation here](https://api.slack.com/messaging/composing/layouts). Slack provides a UI to help create your interactive messages. Check out [Block Kit Builder](https://api.slack.com/tools/block-kit-builder).\n\nAdditionally, there are open-source libraries available that assist with building out UIs for Slack:\n\n* [**Block Builder**](https://github.com/raycharius/slack-block-builder) – Zero-dependency library, with a SwiftUI-like builder syntax.\n* [**JSX-Slack**](https://github.com/speee/jsx-slack) – JSX that transpiles to Slack API-compatible JSON.\n\nInteractive messages using blocks can be sent via any of Botkit's built in functions by passing in the appropriate \"blocks\" as part of the message.  Here is an example:\n\n```javascript\nconst content = {\n    blocks: [{...}]; // insert valid JSON following Block Kit specs\n};\n\nawait bot.reply(message, content);\n```\n\n**Use \"Secondary\" Attachments**\n\nAttachments are still supported by Slack, but the preferred way is to use Block Kit. [Read the official Slack documentation here](https://api.slack.com/reference/messaging/attachments)\n\n\n### [Spawn a worker](../reference/slack.md#create-a-new-slackbotworker)\n\nIt is possible to spawn bot workers bound to a specific team by passing the team ID as the primary parameter to `controller.spawn()`:\n\n```javascript\nlet bot = await controller.spawn(SLACK_TEAM_ID);\n```\n\n### Start or resume conversations with people\n\nUse these method to initiate a conversation with a user, or in a specific channel or thread. After calling these methods, any further actions carried out by the bot worker will happen in that context.\n\nThis can be used to create or resume conversations with users that are not in direct response to an incoming message, like those sent on a schedule or in response to external events.\n\n* [bot.startPrivateConversation()](../reference/slack.md#startprivateconversation)\n* [bot.startConversationInChannel()](../reference/slack.md#startconversationinchannel)\n* [bot.startConversationInThread()](../reference/slack.md#startconversationinthread)\n\n### Slash Commands\n\nSlash commands are special commands triggered by typing a \"/\" then a command. They are configured inside Slack's API portal.\n\n[Read Slack's documentation for Slash commands here &rarr;](https://api.slack.com/slash-commands)\n\nWhen a Botkit application receives a request from a slash command, it will emit a `slash_command` event that can be handled using `controller.on()`.  Several additional reply methods have been provided to handle slash commands.\n\n* [bot.replyPublic()](../reference/slack.md#replypublic)\n* [bot.replyPrivate()](../reference/slack.md#replyprivate)\n\n```javascript\ncontroller.on('slash_command', async(bot, message) => { \n\n    // the /<command> part\n    let command = message.command;\n    // the /command <parameters> part\n    let parameter = message.text;\n\n    await bot.replyPublic(message, 'My response to your command is: ...');\n\n});\n```\n\nNote that if you would prefer to send a response to the Slash command via the synchronous http response back to Slack, you can achieve this by using [bot.httpBody()](../reference/core.md#httpbody).\n\n```javascript\ncontroller.on('slash_command', async(bot, message) => {\n    bot.httpBody({text:'You can send an immediate response using bot.httpBody()'});\n});\n```\n\n### Work with threads\n\nMessages in Slack may now exist as part of a thread, separate from the messages included in the main channel. Threads can be used to create new and interesting interactions for bots.\n\nBotkit's default behavior is for replies to be sent in-context. That is, if a bot replies to a message in a main channel, the reply will be added to the main channel. If a bot replies to a message in a thread, the reply will be added to the thread. This behavior can be changed by using one of the following specialized functions:\n\n* [bot.replyInThread()](../reference/slack.md#replyinthread)\n* [bot.startConversationInThread()](../reference/slack.md#startconversationinthread)\n\n### Ephemeral Messages\n\nMessages can be sent to a user \"ephemerally\" which will only show to them, and no one else. [Learn more about ephemeral messages at the Slack API Documentation.](https://api.slack.com/methods/chat.postEphemeral)\n\n* [bot.replyEphemeral()](../reference/slack.md#replyephemeral)\n\n### Interactive messages\n\nSlack applications can use \"interactive messages\" to include buttons, menus and other interactive elements to improve the user's experience. [See here for how to attach cards and blocks.](#use-attachments-blocks-and-other-rich-message-features)\n\nIf your interactive message contains a button, when the user clicks the button in Slack, Botkit triggers an event based on the message type.\n\nWhen an event is received, your bot can either reply normally, or use the special `bot.replyInteractive` function which will result in the original message in Slack being _replaced_ by the reply. Using `replyInteractive`, bots can present dynamic interfaces inside a single message.\n\nTo receive callbacks, register a callback url as part of applications configuration. Botkit's built in support for the Slack Button system supports interactive message callbacks at same url as other events (`/api/messages` by default). \n\n* [bot.replyInteractive()](../reference/slack.md#replyinteractive)\n\n### Work with Slack Dialogs\n\n[Dialogs](https://api.slack.com/dialogs) allow bots to present multi-field pop-up forms in response to a button click or other interactive message interaction.\nBotkit provides helper functions and special events to make using dialogs in your app possible.\n\nDialogs can be created in response to `interactive_message` or `slash_command` events.\nBotkit provides a specialized reply function, `bot.replyWithDialog()` and a object builder class,\n`SlackDialog` that should be used to create and send the dialog.\n\n* [bot.replyWithDialog()](../reference/slack.md#replywithdialog)\n* [bot.dialogError()](../reference/slack.md#dialogerror)\n* [SlackDialog](../reference/slack.md#slackdialog)\n\n### Update and remove messages\n\nSlack supports updating and deleting messages. Do so with the following convenience methods:\n\n* [bot.updateMessage()](../reference/slack.md#updatemessage)\n* [bot.deleteMessage()](../reference/slack.md#deletemessage)\n\n## Community & Support\n\nJoin our thriving community of Botkit developers and bot enthusiasts at large.\nOver 10,000 members strong, [our open Slack group](https://community.botkit.ai) is\n_the place_ for people interested in the art and science of making bots.\nCome to ask questions, share your progress, and commune with your peers!\n\nYou can also find help from members of the Botkit team [in our dedicated Cisco Spark room](https://eurl.io/#SyNZuomKx)!\n\n## About Botkit\n\nBotkit is a part of the [Microsoft Bot Framework](https://dev.botframework.com).\n\nWant to contribute? [Read the contributor guide](https://github.com/howdyai/botkit/blob/master/CONTRIBUTING.md)\n\nBotkit is released under the [MIT Open Source license](https://github.com/howdyai/botkit/blob/master/LICENSE.md)\n\n"
  },
  {
    "path": "packages/docs/platforms/twilio-sms.md",
    "content": "[&larr; Botkit Documentation](../core.md)  [&larr; Platform Index](index.md) \n\n# botbuilder-adapter-twilio-sms\n\nConnect [Botkit](https://www.npmjs.com/package/botkit) or [BotBuilder](https://www.npmjs.com/package/botbuilder) to Twilio SMS.\n\nThis package contains an adapter that communicates directly with the Twilio API,\nand translates messages to and from a standard format used by your bot. This package can be used alongside your favorite bot development framework to build bots that work with Twilio SMS.\n\n## Install Package\n\nAdd this package to your project using npm:\n\n```bash\nnpm install --save botbuilder-adapter-twilio-sms\n```\n\nImport the adapter class into your code:\n\n```javascript\nconst { TwilioAdapter } = require('botbuilder-adapter-twilio-sms');\n```\n\n## Get Started\n\nIf you are starting a brand new project, [follow these instructions to create a customized application template.](../index.md)\n\n## Use TwilioAdapter in your App\n\nTwilioAdapter provides a translation layer for Botkit and BotBuilder so that bot developers can connect to Twilio SMS and have access to the Twilio API.\n\n### Botkit Basics\n\nWhen used in concert with Botkit, developers need only pass the configured adapter to the Botkit constructor, as seen below. Botkit will automatically create and configure the webhook endpoints and other options necessary for communicating with Twilio.\n\nDevelopers can then bind to Botkit's event emitting system using `controller.on` and `controller.hears` to filter and handle incoming events from the messaging platform. [Learn more about Botkit's core feature &rarr;](../index.md).\n\n[A full description of the TwilioAdapter options and example code can be found in the class reference docs.](../reference/twilio-sms.md#create-a-new-twilioadapter)\n\n```javascript\nconst adapter = new TwilioAdapter({\n    twilio_number: process.env.TWILIO_NUMBER,\n    account_sid: process.env.TWILIO_ACCOUNT_SID,\n    auth_token: process.env.TWILIO_AUTH_TOKEN,\n});\n\nconst controller = new Botkit({\n    adapter,\n    // ...other options\n});\n\ncontroller.on('message', async(bot, message) => {\n    await bot.reply(message, 'I heard a message!');\n});\n```\n\n### BotBuilder Basics\n\nAlternately, developers may choose to use `TwilioAdapter` with BotBuilder. With BotBuilder, the adapter is used more directly with a webserver, and all incoming events are handled as [Activities](https://docs.microsoft.com/en-us/javascript/api/botframework-schema/activity?view=botbuilder-ts-latest).\n\n```javascript\nconst adapter = new TwilioAdapter({\n    twilio_number: process.env.TWILIO_NUMBER,\n    account_sid: process.env.TWILIO_ACCOUNT_SID,\n    auth_token: process.env.TWILIO_AUTH_TOKEN,\n});\n\n\nconst server = restify.createServer();\nserver.use(restify.plugins.bodyParser());\nserver.post('/api/messages', (req, res) => {\n     adapter.processActivity(req, res, async(context) => {\n         await context.sendActivity('I heard a message!');\n     });\n});\n```\n\n## Class Reference\n\n* [TwilioAdapter](../reference/twilio-sms.md#twilioadapter)\n* [BotWorker Extensions](../reference/twilio-sms.md#twiliobotworker)\n\n## Event List\n\nBotkit will emit the following events: \n\n| Event | Description\n|--- |---\n| message | a message from a user\n| picture_message | a message with a picture attached\n\n## Calling Twilio APIs\n\nThis package exposes a pre-configured [Twilio API client](https://www.twilio.com/docs/libraries/node) for developers who want to use one of the many available API endpoints.\n\nIn Botkit handlers, the `bot` worker object passed into all handlers will contain a `bot.api` field that contains the client, preconfigured and ready to use.\n\n\n```javascript\ncontroller.on('message', async(bot, message) {\n\n    // create a message using the API directly\n    let res = await bot.api.messages.create(my_message_object);\n\n});\n```\n\n## Botkit Extensions\n\nIn Botkit handlers, the `bot` worker for Twilio contains [all of the base methods](../reference/core.md#BotWorker) as well as the following platform-specific extensions:\n\n### [bot.startConversationWithUser()](../reference/twilio-sms.md#startconversationwithuser)\n\nUse this method to initiate a conversation with a user. After calling this method, any further actions carried out by the bot worker will happen with the specified user.\n\nThis can be used to create or resume conversations with users that are not in direct response to an incoming message, like those sent on a schedule or in response to external events.\n\n## Community & Support\n\nJoin our thriving community of Botkit developers and bot enthusiasts at large.\nOver 10,000 members strong, [our open Slack group](https://community.botkit.ai) is\n_the place_ for people interested in the art and science of making bots.\nCome to ask questions, share your progress, and commune with your peers!\n\nYou can also find help from members of the Botkit team [in our dedicated Cisco Spark room](https://eurl.io/#SyNZuomKx)!\n\n## About Botkit\n\nBotkit is a part of the [Microsoft Bot Framework](https://dev.botframework.com).\n\nWant to contribute? [Read the contributor guide](https://github.com/howdyai/botkit/blob/master/CONTRIBUTING.md)\n\nBotkit is released under the [MIT Open Source license](https://github.com/howdyai/botkit/blob/master/LICENSE.md)\n\n"
  },
  {
    "path": "packages/docs/platforms/web.md",
    "content": "[&larr; Botkit Documentation](../core.md)  [&larr; Platform Index](index.md) \n\n# botbuilder-adapter-web\nConnect [Botkit](https://www.npmjs.com/package/botkit) or [BotBuilder](https://www.npmjs.com/package/botbuilder) to the Web.\n\nThis package contains an adapter that communicates directly with the web via webhooks or websocket connections.\nThis package can be used alongside your favorite bot development framework to build bots that work on a website or within an existing app.\n\n## Install Package\n\nAdd this package to your project using npm:\n\n```bash\nnpm install --save botbuilder-adapter-web\n```\n\nImport the adapter class into your code:\n\n```javascript\nconst { WebAdapter } = require('botbuilder-adapter-web');\n```\n\n## Get Started\n\nIf you are starting a brand new project, [follow these instructions to create a customized application template.](../index.md)\n\n## Use WebAdapter in your App\n\nWebAdapter provides a translation layer for Botkit and BotBuilder so that bot developers can connect directly to users on the web.\n\n### Botkit Basics\n\nWhen used in concert with Botkit, developers need only pass the configured adapter to the Botkit constructor, as seen below. Botkit will automatically create and configure the webhook endpoints and other options necessary for communicating with the web.\n\nDevelopers can then bind to Botkit's event emitting system using `controller.on` and `controller.hears` to filter and handle incoming events from the messaging platform. [Learn more about Botkit's core feature &rarr;](../index.md).\n\n[A full description of the WebAdapter options and example code can be found in the class reference docs.](../reference/web.md#create-a-new-webadapter)\n\n```javascript\nconst adapter = new WebAdapter();\nconst controller = new Botkit({\n    adapter,\n    // ...other options\n});\n\n// TODO: expose chat client\n\ncontroller.on('message', async(bot, message) => {\n    await bot.reply(message, 'I heard a message!');\n});\n```\n\n### BotBuilder Basics\n\nAlternately, developers may choose to use `WebAdapter` with BotBuilder. With BotBuilder, the adapter is used more directly with a webserver, and all incoming events are handled as [Activities](https://docs.microsoft.com/en-us/javascript/api/botframework-schema/activity?view=botbuilder-ts-latest).\n\n[Read more &rarr;](../reference/web.md#create-a-new-webadapter)\n\n## Class Reference\n\n* [WebAdapter](../reference/web.md#webadapter)\n\n## Reference Chat Client\n\nThis package includes [a reference implementation of a chat client written in HTML/JS/CSS](https://github.com/howdyai/botkit/tree/master/packages/botbuilder-adapter-web/client/#readme) that serves as a base for building a customized chat widget.\n\n> [Using typing indicators with the reference chat client](https://github.com/howdyai/botkit/tree/master/packages/botbuilder-adapter-web/client/#typing-indicators)\n\n## Event List\n\n| Event | Description\n|--- |---\n| message | a message sent by the user\n| hello | event sent when a user first connects\n| welcome_back | event sent when a user reconnects\n| identify | an extended user profile is being sent by the client to be associated with the user id\n\n## Botkit Extensions\n\nIn Botkit handlers, the `bot` worker for web contains [all of the base methods](../reference/core.md) as well as the following platform-specific extensions:\n\n### [adapter.createSocketServer()](../reference/web.md#createsocketserver)\n\nConfigures the webserver to accept websocket connections. This method is called automatically by Botkit, but must be manually called when using with BotBuilder.\n\n## Community & Support\n\nJoin our thriving community of Botkit developers and bot enthusiasts at large.\nOver 10,000 members strong, [our Github site](https://github.com/howdyai/botkit) is\n_the place_ for people interested in the art and science of making bots.\nCome to ask questions, share your progress, and commune with your peers!\n\nYou can also find help from members of the Botkit team [in our dedicated Cisco Spark room](https://eurl.io/#SyNZuomKx)!\n\n## About Botkit\n\nBotkit is a part of the [Microsoft Bot Framework](https://dev.botframework.com).\n\nWant to contribute? [Read the contributor guide](https://github.com/howdyai/botkit/blob/master/CONTRIBUTING.md)\n\nBotkit is released under the [MIT Open Source license](https://github.com/howdyai/botkit/blob/master/LICENSE.md)\n\n"
  },
  {
    "path": "packages/docs/platforms/webex.md",
    "content": "[&larr; Botkit Documentation](../core.md)  [&larr; Platform Index](index.md) \n\n# botbuilder-adapter-webex\nConnect [Botkit](https://www.npmjs.com/package/botkit) or [BotBuilder](https://www.npmjs.com/package/botbuilder) to Webex Teams.\n\nThis package contains an adapter that communicates directly with the Webex Teams API,\nand translates messages to and from a standard format used by your bot. This package can be used alongside your favorite bot development framework to build bots that work with Webex Teams.\n\n## Install Package\n\nAdd this package to your project using npm:\n\n```bash\nnpm install --save botbuilder-adapter-webex\n```\n\nImport the adapter class into your code:\n\n```javascript\nconst { WebexAdapter } = require('botbuilder-adapter-webex');\n```\n\n## Get Started\n\nIf you are starting a brand new project, [follow these instructions to create a customized application template.](../index.md)\n\n## Use WebexAdapter in your App\n\nWebexAdapter provides a translation layer for Botkit and BotBuilder so that bot developers can connect to Webex Teams and have access to Webex's API.\n\n### Botkit Basics\n\nWhen used in concert with Botkit, developers need only pass the configured adapter to the Botkit constructor, as seen below. Botkit will automatically create and configure the webhook endpoints and other options necessary for communicating with Webex.\n\nDevelopers can then bind to Botkit's event emitting system using `controller.on` and `controller.hears` to filter and handle incoming events from the messaging platform. [Learn more about Botkit's core feature &rarr;](../index.md).\n\n[A full description of the WebexAdapter options and example code can be found in the class reference docs.](../reference/webex.md#create-a-new-webexadapter)\n\n```javascript\nconst adapter = new WebexAdapter({\n    access_token: process.env.ACCESS_TOKEN,\n    public_address: process.env.PUBLIC_ADDRESS,\n    secret: process.env.SECRET \n});\n\nconst controller = new Botkit({\n    adapter,\n    // ...other options\n});\n\ncontroller.on('message', async(bot, message) => {\n    await bot.reply(message, 'I heard a message!');\n});\n```\n\n### BotBuilder Basics\n\nAlternately, developers may choose to use `WebexAdapter` with BotBuilder. With BotBuilder, the adapter is used more directly with a webserver, and all incoming events are handled as [Activities](https://docs.microsoft.com/en-us/javascript/api/botframework-schema/activity?view=botbuilder-ts-latest).\n\n```javascript\nconst adapter = new WebexAdapter({\n    access_token: process.env.ACCESS_TOKEN,\n    public_address: process.env.PUBLIC_ADDRESS,\n    secret: process.env.SECRET \n});\n\nconst server = restify.createServer();\nserver.use(restify.plugins.bodyParser());\nserver.post('/api/messages', (req, res) => {\n     adapter.processActivity(req, res, async(context) => {\n         await context.sendActivity('I heard a message!');\n     });\n});\n```\n\n## Class Reference\n\n* [WebexAdapter](../reference/webex.md#webexadapter)\n* [BotWorker Extensions](../reference/webex.md#webexbotworker)\n\n## Event List\n\nAll events [listed here](https://developer.webex.com/webhooks-explained.html#resources-events) should be expected, in the format `resource`.`event` - for example, `rooms.created`.  \n\n| Event | Description\n|--- |---\n| message |\n| self_message | \n\n\n## Calling Webex APIs\n\nThis package exposes a pre-configured [Webex API client](https://www.npmjs.com/package/webex) for developers who want to use one of the many available API endpoints.\n\nIn Botkit handlers, the `bot` worker object passed into all handlers will contain a `bot.api` field that contains the client, preconfigured and ready to use.\n\n```javascript\ncontroller.on('message', async(bot, message) {\n\n    // get a list of the members of a room\n    let members = await bot.api.memberships.get(message.channel);\n    // .. do stuff\n});\n```\n\n## Botkit Extensions\nIn Botkit handlers, the `bot` worker for Webex contains [all of the base methods](../reference/core.md#BotWorker) as well as the following platform-specific extensions:\n\n### [bot.startConversationInRoom()](../reference/webex.md#startconversationinroom)\n\nUse this method to initiate a conversation with a user in a given, known room.  After calling this method, any further actions carried out by the bot worker will happen in that context.\n\nThis can be used to create or resume conversations with users that are not in direct response to an incoming message, like those sent on a schedule or in response to external events.\n\n### [bot.startPrivateConversation()](../reference/webex.md#startprivateconversation)\n\nUse this method to initiate a private 1:1 conversation with a user.\n\nCalling this method will create or switch to the private 1:1 room for any messages sent with `bot.say`. However, due to a quirk in the Webex protocol, multi-message dialogs started with `beginDialog` will not work.\n\n### Remove messages\n\nWebex Teams supports deleting messages. Do so with the following convenience method:\n\n* [bot.deleteMessage](../reference/webex.md#deletemessage)\n\n## Community & Support\n\nJoin our thriving community of Botkit developers and bot enthusiasts at large.\nOver 10,000 members strong, [our open Slack group](https://community.botkit.ai) is\n_the place_ for people interested in the art and science of making bots.\nCome to ask questions, share your progress, and commune with your peers!\n\nYou can also find help from members of the Botkit team [in our dedicated Cisco Spark room](https://eurl.io/#SyNZuomKx)!\n\n## About Botkit\n\nBotkit is a part of the [Microsoft Bot Framework](https://dev.botframework.com).\n\nWant to contribute? [Read the contributor guide](https://github.com/howdyai/botkit/blob/master/CONTRIBUTING.md)\n\nBotkit is released under the [MIT Open Source license](https://github.com/howdyai/botkit/blob/master/LICENSE.md)\n\n"
  },
  {
    "path": "packages/docs/plugins/cms.md",
    "content": "[&larr; Botkit Documentation](../core.md)  [&larr; Plugin Index](index.md) \n\n# botkit-plugin-cms\n\nUse and extend dialogs authored remotely using [Botkit CMS](https://github.com/howdyai/botkit-cms#readme).\n\n## Install Package\n\nAdd this package to your project using npm:\n\n```bash\nnpm install --save botkit-plugin-cms\n```\n\nImport the adapter class into your code:\n\n```javascript\nconst { BotkitCMSHelper } = require('botkit-plugin-cms');\n```\n\n## Use in your App\n\nConfigure the plugin with the URI of your Botkit CMS instance and a token set in the CMS config.\nThese values are available from the cms admin dashboard's options tab.\n\nThen, register the plugin and it's features with the Botkit controller using `usePlugin()`\n\n```javascript\nlet cms = new BotkitCMSHelper({\n    uri: 'https://someurl.com/',\n    token: 'some-token-value'\n});\n\ncontroller.usePlugin(cms);\n```\n\nOnce registered, Botkit will automatically load all of the available content from the Botkit CMS api and dynamically create [BotkitConversation Dialogs](../reference/core.md#botkitconversation) for use in The bot.  [All of the plugin's methods](../reference/cms.md) will be available at `controller.plugins.cms`.\n\nTo evaluate all incoming messages for triggers configured in the CMS, and automatically respond by starting the appropriate dialog, use [controller.plugins.cms.testTrigger()](../reference/cms.md#testtrigger):\n\n```javascript\n// use the cms to test remote triggers\ncontroller.on('message', async(bot, message) => {\n  let triggered = await controller.plugins.cms.testTrigger(bot, message);\n  \n  // if a script was triggered, return false from the handler.\n  // this stops botkit from any further processing.\n  if (triggered !== false) {\n      return false;\n  }\n});\n```\n\nIn most cases, calls to `testTrigger` should come at the _end_ of the bot's message evaluation process. Since Botkit fires handlers in the order in which they are added to the controller, this call should most often be placed _after_ other trigger definintions - particularly if the CMS has been configured with a fallback script which will ALWAYS fire even if no matching trigger is found.\n\n## Hooking code to your CMS-powered Dialogs\n\nSince under the hood, this plugin creates [BotkitConversation Dialogs](../reference/core.md#botkitconversation), all of the same [hooks](../conversations.md#hooks), [templating features](../conversations.md#using-variable-tokens-and-templates-in-conversation-threads), and special actions are available. However, since the dialogs are built dynamically, special methods are necessary to _find the dialog by name_ within Botkit's collection of dialogs before binding hooks.\n\n* [controller.plugins.cms.before()](../reference/cms.md#before)\n* [controller.plugins.cms.onChange()](../reference/cms.md#onchange)\n* [controller.plugins.cms.after()](../reference/cms.md#after)\n\nFor example, if the CMS has a script called `onboarding`, hook functions can be bound to it like so:\n\n```javascrit\n// wrap calls to the plugin in controller.ready to ensure the content has successfully loaded\ncontroller.ready(function() {\n\n    // fire before onboarding begins\n    controller.plugins.cms.before('onboarding', async(convo, bot) => {\n        convo.setVar('timestamp', new Date());\n    });\n\n    // fire after onboarding ends\n    controller.plugins.cms.after('onboarding', async(results, bot) => {\n        // do something like store results in the db\n\n        // take the next step...\n        await bot.say('ONBOARDING COMPLETE!');\n    });\n});\n```\n\n## Class Reference\n\n* [BotkitCMSHelper](../reference/cms.md)\n\n## About Botkit\n\nBotkit is a part of the [Microsoft Bot Framework](https://dev.botframework.com).\n\nWant to contribute? [Read the contributor guide](https://github.com/howdyai/botkit/blob/master/CONTRIBUTING.md)\n\nBotkit is released under the [MIT Open Source license](https://github.com/howdyai/botkit/blob/master/LICENSE.md)"
  },
  {
    "path": "packages/docs/plugins/index.md",
    "content": "# Botkit Plugins\n\n[&larr; Botkit Core Docs](../core.md)\n\n* [Botkit CMS Plugin](../plugins/cms.md)\n"
  },
  {
    "path": "packages/docs/provisioning/cisco-spark.md",
    "content": "# Configure Botkit and Cisco Webex Teams\n\nSetting up a bot for Cisco Webex Teams is one of the easiest experiences for bot developers! Follow these steps carefully to configure your bot.\n\n### 1. Install Botkit\n\nYou will need to [install Botkit](../platforms/webex.md#get-started) and run it before your bot can be configured with Cisco Spark.\n\n### 2. Create a new bot in the Cisco Developer portal\n\nFollow the instructions to create a new bot in the [Cisco Webex Teams Developer Portal](https://developer.ciscospark.com/add-bot.html).\n\n![Screenshot of the 'Add a bot' flow in Webex developer portal](IMG/cisco_add.png)\n\nTake note of the bot username, you'll need it later.\n\n**Note about your icon**: Cisco requires you host an avatar for your bot before you can create it in their portal. This bot needs to be a 512x512px image icon hosted anywhere on the web. This can be changed later.\n\nYou can copy and paste this URL for a Botkit icon you can use right away:\n\nhttps://raw.githubusercontent.com/howdyai/botkit-starter-ciscospark/master/public/default_icon.png\n\n### 3. Copy your access token\n\nCisco will provide you an `access token` that is specific to your bot. Write this down, you won't be able to see this later (but you will be able revoke it and create a new one).\n\n### 4. Run your bot with variables set\n\n [Follow these instructions](../platforms/webex.md#get-started) to run your bot locally, or by using a third-party service such as [Glitch](https://glitch.com) or [Heroku](https://heroku.com).\n\n You will need the following environment variables when running your bot:\n\n * `access_token` = Your token from Webex Teams (**required**)\n * `secret` = User-defined string to validate payloads  (**required**)\n * `public_address`=  URL of your bot server (**required**)\n\nYou should now be able to search your Webex Teams for the bot username you defined, and add it to your team!\n\n### Additional resources\n\nRead more about making bots for this platform in the [Webex Developer Portal](https://developer.webex.com/docs/bots).\n"
  },
  {
    "path": "packages/docs/provisioning/facebook_messenger.md",
    "content": "# Configure Botkit and Facebook Messenger\n\n*Note: This also applies for [Facebook Workplace](https://www.facebook.com/workplace)*\n\nFacebook is a constantly evolving platform, nominally you can find everything you [need to create a bot](https://developers.facebook.com/docs/messenger-platform/guides/quick-start) on their platform page, but that information is subject to change.\n\n### 1. [Install Botkit](../index.md)\n\nOnce installed, you will need to do steps 2-4, and steps 5 in parallel. It helps to have your development enviroment and the Facebook for Developers page open at the same time.\n\n### 2. Create a Facebook App for Web\n\nVisit [Facebook for Developers page](https://developers.facebook.com/tools-and-support/) and create a new app.\n\n![Screenshot of create an APP ID in Facebook developer portal](IMG/fb_new.png)\n\n* Select a Messenger application\n\n![Screenshot of configuring your app in the Facebook developer portal](IMG/fb_mess.png)\n\n### 3. Get a Page Access Token for your app\nScroll down to `Token Generation`\n\n![Screenshot of page access tokens in Facebook portal](IMG/fb_tokengen.png)\n\nIf you have not yet created your page yet, you can go ahead and do this now, or associate this new bot with an existing page.\n\nCopy this `Page Access Token`, you'll need it when running your bot.\n\n### 4. Setup webhooks\nClick  `Setup Webhooks` to link this application to your Botkit instance.\n\n![Screenshot of configuring webhooks in the Facebook portal](IMG/fb_webhooks.png)\n\nThe callback url will be `https://YOURURL/api/messages`. This URL must be publically available, and SSL-secured. More information on this can be found in the next step.\n\nYou will also need to define a `Verify Token` for your page subscription. This is a user-defined string that you will keep secret and pass in with your environment variables.\n\n### 5. Run your application\n\nRun your application with your environment variables set:\n\n* `page_token` - Your Page Access Token (**required**)\n* `verify_token` - Your Verify Token (**required**)\n\nIf your application has been configured correctly, you will be able to talk to your bot through the page you specified in Step 3. Congratulations!\n\n### Additional resources\n*  [Botkit Facebook readme](../platforms/facebook.md)\n*  [Botkit Facebook Starter Kit](https://github.com/howdyai/botkit-starter-facebook)\n*  [Messenger Platform Documentation](https://developers.facebook.com/products/messenger/)\n*  [Submit your bot so it can be publically available](https://developers.facebook.com/docs/messenger-platform/submission-process)\n"
  },
  {
    "path": "packages/docs/provisioning/index.md",
    "content": "# Provisioning Botkit\nAs Botkit adds more platforms, it becomes increasingly difficult to keep track of all the methods for provisioning your bot on the various platforms we support.\n\nTo help Botkit developers, we are pulling out detailed provisioning documents for each platform and keeping them in this directory. Our hope is that this will make our docs more flexible to platform changes, and clearly show the fastest way to stand up your bot!\n\n## Platforms\n\n### [Slack Events API](slack-events-api.md)\n\n### [Microsoft Teams](teams.md)\n\n### [Facebook Messenger](facebook_messenger.md)\n\n### [Webex Teams](cisco-spark.md)\n\n### [SMS from Twilio](twilio-sms.md)\n"
  },
  {
    "path": "packages/docs/provisioning/slack-events-api.md",
    "content": "# Configure Botkit and the Slack Events API\n\nBuilding a bot with Botkit and the Slack Events API gives you access to all of the best tools and options available to create a feature-rich bot for Slack.\n\nIn order to get everything set up, you will need to configure a new Slack App inside the [Slack Developer Portal](http://api.slack.com/apps), and at the same time, configure a Botkit-powered bot. It only takes a few moments, but there are a bunch of steps, so follow these instructions carefully. \n\nThis feature is still in very active development at Slack, and these steps are subject to change.\n\n## 1. Create a new Slack App\n\nGo to [http://api.slack.com/apps](http://api.slack.com/apps) and create a new application record.\n\n![Create your app](IMG/slack-new.png)\t\n\nYou will receive a `clientId` and a `clientSecret`. You need these values - copy them into a temporary text file for use in the following steps.\n\n## 2. Turn on your Botkit app\n\nYou will need to [install Botkit](../platforms/slack.md#get-started) and run it before your bot can be configured with Slack.\n\nOnce you've collected your `clientId` and `clientSecret` tokens from Slack, you can start your Botkit app. You will need to have a bot service online and reachable over the web to complete the following steps and finish setting up your bot.\n\n## 3. Configure OAuth\n\nBotkit and Slack use the OAuth authentication system to grant bots access to connect to, read from, and send messages to Slack teams.\n\nClick on the \"OAuth & Permissions\" tab in your Slack's app setting, and under Redirect URLs, add: `https://my-bot-url/install/auth`, and save your progress.\n\n## 4. Add a Bot User\n\nClick on the \"Bot Users\" tab and specify a name for your bot. This is the name that will be used by default when your application creates a new bot on a user's team. \n\n![A screenshot of the \"Bot User\" screen on Slack's portal](IMG/slack-botuser.png)\n\nIn addition to a name, enable the option for \"Always Show My Bot Online.\" This will ensure your Bot appears online to your team.\n\n## 5. Set up Interactive Components\n\n\"Interactive Components\" is Slack's fancy way of saying \"buttons, or dialogs, or menus.\" In order to enable these, under Request URL, add `https://YOURURL/api/messages`, then click save.\n\n## 6. Set up Event Subscriptions\n\nTo start receiving messages, you will need to enable Event Subscriptions. Finally, scroll to the top of the page and switch \"Enable Events\" to \"on\". \n\nNext you will need to add your Request URL, like this: `https://YOURURL/api/messages`. When you finish typing, Slack will verify that this endpoint is properly configured. You must be running your Botkit application at the URL specified for this to work.\n\nOnce verified, click \"Add Bot User Event\", and using the dropdown that appears, select all of the `message.*` events: \n\n* `message.channels`\n* `message.groups`\n* `message.im`\n* `message.mpim`\n\nThis configuration tells Slack to send your bot all messages that are sent in any channel or group in which your bot is present. Add other events as needed. \n\n![A screenshot showing how to add message subscriptions](IMG/slack_botevents.png)\n\nYour bot is now ready to receive messages!\n\n*Problems?* : If you do not see `Bot User` here, it is likely that you forgot to add a Bot User back in Step 4. Go and fix that now, and come back to Step 6 to continue.\n\n*Note*: If you intend on submitting to the App Directory, be sure to have a good reason to request more widely ranging events as your app can be rejected for excessively wide permissions.\n\n## 7. Add your bot to your Slack team\n\nNow that your bot is configured, and your application is up and running, you can login and add your bot. Visit `https://MYURL/install`, and you will be automatically directed to Slack's login page. Login and choose a team. You'll get one more confirmation before being redirected back to your app.\n\nMeanwhile, your bot should appear inside your Slack team. You should receive a friendly welcome message to indicates your bot is now online and working! \n\n## Additional resources \n* [Botkit Slack readme](../platforms/slack.md) \n* [Slack's official documention for Events API](https://api.slack.com/events-api)\n"
  },
  {
    "path": "packages/docs/provisioning/teams.md",
    "content": "# Configure Botkit and Microsoft Teams\nBuilding a bot with Botkit and the Microsoft Teams API gives you access to all of the best tools and options available to create a feature-rich app for Teams.\n\nWe've created the following guide to help you configure your Microsoft Teams bot. \n\n## Step 1 Register your bot with Bot Framework\nMicrosoft Teams first requires you to register with their \"Bot Framework\" before you can add a bot to your Teams team. This is a multi-step process:\n\n### Create an account / Log in\n\nLog into the [Bot Framework Developer Portal](https://dev.botframework.com/bots/) using your Microsoft credentials, or create an account.\n\n### Register a new bot\nOnce you are logged in, [click this link to create a new bot](https://dev.botframework.com/bots/new) and then you can skip the next two steps!\n\n* Click on `My Bots` and then Register. Choose `Create a bot with the Bot Builder SDK`, and click `Create`.\n\n* Select `Register an existing bot built using Bot Builder SDK` from the next menu and then click `OK`.\n\nYou will be asked some questions about your bot. Some of these can be changed later, but some _cannot be changed_ so consider your responses carefully!\n\nThese are the important fields when creating your bot:\n\n* `Display name` - Your bot's name in channels and directories. This can be changed later.\n* `Bot handle` - This will be used in the URL for your bot. *Note: This cannot be changed.*\n* `Messaging endpoint` - You may not know this yet, as you will be creating this in the next step when setting up the Botkit app. By default it is: `https://YOURURL/api/messages`.\n\n### Generate your keys\nRegister your bot with Microsoft by clicking: `Create Microsoft App ID and password`\n\nThis action will take you to a new website (and require you to log in again) and then ask you for an `App name`.\n\nOnce added, it will provide an `App ID` which you need to copy somewhere safe to use in the next step.\n\nNext, click `Generate password`. *This will only be shown to you once, if you lose it, you will need to invalidate the old one and set this up again!*\n\nClick Register.\n\n### Add the Microsoft Teams channel\n\nAdd the Microsoft Teams channel from the list of channels, making sure the `Enabled` is set to on.\n\nYou will want to leave this window open as you finish setting up Botkit, as you will need to come back here before you are done.\n\n## Step 4 - Deploy your bot and install to a team\n\n### Turn on your Botkit app\nNow that everything is setup on Microsoft's side, you can run Botkit with the information created in the Bot Framework.\n\n### Update your Messaging Endpoint in Bot Framework\nOnce a Botkit instance is running, you may have a new URL that you will have to update in the bot's settings [in Microsoft Bot Framework](https://dev.botframework.com/bots/).\n\nOnce logged in to that page:\n\n* Click on your bot\n* Select settings\n* Scroll down to the messaging endpoint field and replace the placeholder URL with your active Botkit URL (it should look something like `https://YOURURL/api/messages`).\n* Click Save.\n\n### Create your Application Manifest\nTo add a development bot on a team, you will need to prepare an [App Package](https://msdn.microsoft.com/en-us/microsoft-teams/createpackage).\n\n### Sideload your Bot to Microsoft Teams\nAfter creating your app package, you can [load it easily into your development team](https://msdn.microsoft.com/en-us/microsoft-teams/sideload#load-your-package-into-a-team).\n\nSay hello to your real live bot!\n\n## Step 5 - Add dialog and features\nOnce you have a bot up and running, you can start the fun part of [making your bot functional](../core.md).\n\nIf you have questions or suggestions, please take a look at our [community support resources](core.md#developer--support-community).\n\n## Additional resources\n* [Microsoft's Bot Framework](https://dev.botframework.com/)\n"
  },
  {
    "path": "packages/docs/provisioning/twilio-sms.md",
    "content": "# Configure Botkit and Twilio SMS\n\nSetting up a bot for Twilio SMS is one of the easiest experiences for bot developers! Follow these steps carefully to configure your bot.\n\n### 1. Install Botkit\n\nYou will need to [install Botkit](../platforms/twilio-sms.md#get-started) and run it before your bot can be configured with Twilio SMS.\n\n### 2. Create a new bot in the Twilio Developer Console\n\nLogin and click `Get Started`  in [Twilio SMS Developer Console](https://www.twilio.com/console/sms/dashboard). You will be taken through the process of obtaining a number to use with your bot.\n\nAt this point you can use the Twilio wizard to help you create an application, or build one directly by clicking `Messanging Services`. You can give it a friendly, and chose `Mixed` for use case.\n\nCheck the box `Process Inbound Messages` and under request URL, type the name of your request url.\n\nBy default in Botkit, this is:\nhttps://*mybot.yoururl.com*/api/messages\n\n### 3. Collect your tokens\n\nNext, visit [your console Dashboard](https://www.twilio.com/console) and copy your `Account SID` and `Auth Token`. You will use these in the next step along with your assignedmobile number to setup Botkit.\n\n### 4. Run your bot with variables set\n\n [Follow these instructions](../platforms/twilio-sms.md#get-started) to run your bot locally, or by using a third-party service such as [Glitch](https://glitch.com) or [Heroku](https://heroku.com).\n\n You will need the following environment variables when running your bot:\n\n* TWILIO_ACCOUNT_SID= Your account's SID collected in step 3 above.\n* TWILIO_AUTH_TOKEN= Your account's Auth Token collected in step 3 above.\n* TWILIO_NUMBER= The number you were assigned in step 2 above.\n\nYou should now be able to text message your number the words `Hello` and receive a friendly reply back!\n\n### Additional resources\n\nRead more about making bots for this platform in the [Twilio Developer Portal](https://www.twilio.com/console).\n"
  },
  {
    "path": "packages/docs/readme.md",
    "content": "# Botkit 4.x Docs\n\nThis repo contains the source material for the official Botkit 4.x docs.\n\n* [Get Started](index.md)\n* [Plugins](plugins/index.md)\n* [Platform Adapters](platforms/index.md)\n* [Class Reference](reference/index.md)\n\n#### Building the Docs\n\n_Most_ of these documents are automatically generated from the source and by aggregating information from the various adapter and plugin packages.  Do not manually edit files in `platforms/` `plugins/` or `reference/`\n\nTo build new versions of these docs, run:\n\n```bash\nlerna run build\nlerna run build-docs\n```\n"
  },
  {
    "path": "packages/docs/reference/cms.md",
    "content": "# Botkit CMS Plugin Class Reference\n\n[&larr; Botkit Documentation](../core.md) [&larr; Class Index](index.md) \n\nThis is a class reference for all the methods exposed by the [botkit-plugin-cms](https://github.com/howdyai/botkit/tree/master/packages/botkit-plugin-cms) package.\n\n## Classes\n\n\n* <a href=\"#BotkitCMSHelper\" aria-current=\"page\">BotkitCMSHelper</a>\n\n## Interfaces\n\n* <a href=\"#CMSOptions\" aria-current=\"page\">CMSOptions</a>\n\n---\n\n<a name=\"BotkitCMSHelper\"></a>\n## BotkitCMSHelper\nA plugin for Botkit that provides access to an instance of [Botkit CMS](https://github.com/howdyai/botkit-cms), including the ability to load script content into a DialogSet\nand bind before, after and onChange handlers to those dynamically imported dialogs by name.\n\n```javascript\ncontroller.use(new BotkitCMSHelper({\n     uri: process.env.CMS_URI,\n     token: process.env.CMS_TOKEN\n}));\n\n// use the cms to test remote triggers\ncontroller.on('message', async(bot, message) => {\n  await controller.plugins.cms.testTrigger(bot, message);\n});\n```\n\n\nTo use this class in your application, first install the package:\n```bash\nnpm install --save botkit-plugin-cms\n```\n\nThen import this and other classes into your code:\n```javascript\nconst { BotkitCMSHelper } = require('botkit-plugin-cms');\n```\n\nThis class includes the following methods:\n* [after()](#after)\n* [before()](#before)\n* [init()](#init)\n* [loadAllScripts()](#loadAllScripts)\n* [onChange()](#onChange)\n* [testTrigger()](#testTrigger)\n\n\n\n### Create a new BotkitCMSHelper()\n**Parameters**\n\n| Argument | Type | Description\n|--- |--- |---\n| config | [CMSOptions](#CMSOptions) | \n\n\n\n\n## Properties and Accessors\n\n| Name | Type | Description\n|--- |--- |---\n| name | string | Botkit Plugin name\n\n## BotkitCMSHelper Class Methods\n<a name=\"after\"></a>\n### after()\nBind a handler function that will fire after a given dialog ends.\nProvides a way to use BotkitConversation.after() on dialogs loaded dynamically via the CMS api instead of being created in code.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| script_name| string | The name of the script to bind to\n| handler|  | A handler function in the form async(results, bot) => {}<br/>\n\n\n\n```javascript\ncontroller.plugins.cms.after('my_script', async(results, bot) => {\n\nconsole.log('my_script just ended! here are the results', results);\n\n});\n```\n\n\n<a name=\"before\"></a>\n### before()\nBind a handler function that will fire before a given script and thread begin.\nProvides a way to use BotkitConversation.before() on dialogs loaded dynamically via the CMS api instead of being created in code.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| script_name| string | The name of the script to bind to\n| thread_name| string | The name of a thread within the script to bind to\n| handler|  | A handler function in the form async(convo, bot) => {}<br/>\n\n\n\n```javascript\ncontroller.cms.before('my_script','my_thread', async(convo, bot) => {\n\n // do stuff\n console.log('starting my_thread as part of my_script');\n // other stuff including convo.setVar convo.gotoThread\n\n});\n```\n\n\n<a name=\"init\"></a>\n### init()\nBotkit plugin init function\nAutoloads all scripts into the controller's main dialogSet.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| botkit| any | A Botkit controller object<br/>\n\n\n\n<a name=\"loadAllScripts\"></a>\n### loadAllScripts()\nLoad all script content from the configured CMS instance into a DialogSet and prepare them to be used.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| botkit| Botkit | \n\n\n\n<a name=\"onChange\"></a>\n### onChange()\nBind a handler function that will fire when a given variable is set within a a given script.\nProvides a way to use BotkitConversation.onChange() on dialogs loaded dynamically via the CMS api instead of being created in code.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| script_name| string | The name of the script to bind to\n| variable_name| string | The name of a variable within the script to bind to\n| handler|  | A handler function in the form async(value, convo, bot) => {}<br/>\n\n\n\n```javascript\ncontroller.plugins.cms.onChange('my_script','my_variable', async(new_value, convo, bot) => {\n\nconsole.log('A new value got set for my_variable inside my_script: ', new_value);\n\n});\n```\n\n\n<a name=\"testTrigger\"></a>\n### testTrigger()\nUses the Botkit CMS trigger API to test an incoming message against a list of predefined triggers.\nIf a trigger is matched, the appropriate dialog will begin immediately.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| bot| BotWorker | The current bot worker instance\n| message| Partial&lt;BotkitMessage&gt; | An incoming message to be interpretted\n\n\n**Returns**\n\nReturns false if a dialog is NOT triggered, otherwise returns void.\n\n\n\n\n\n\n<a name=\"CMSOptions\"></a>\n## Interface CMSOptions\n\n\n**Fields**\n\n| Name | Type | Description\n|--- |--- |---\n| controller | Botkit | \n| token | string | \n| uri | string | \n"
  },
  {
    "path": "packages/docs/reference/core.md",
    "content": "# Botkit Core Class Reference\n\n[&larr; Botkit Documentation](../core.md) [&larr; Class Index](index.md) \n\nThis is a class reference for all the methods exposed by the [botkit](https://github.com/howdyai/botkit/tree/master/packages/botkit) package.\n\n## Classes\n\n\n* <a href=\"#Botkit\" aria-current=\"page\">Botkit</a>\n* <a href=\"#BotkitBotFrameworkAdapter\" aria-current=\"page\">BotkitBotFrameworkAdapter</a>\n* <a href=\"#TeamsBotWorker\" aria-current=\"page\">TeamsBotWorker</a>\n* <a href=\"#BotWorker\" aria-current=\"page\">BotWorker</a>\n* <a href=\"#BotkitConversation\" aria-current=\"page\">BotkitConversation</a>\n* <a href=\"#BotkitDialogWrapper\" aria-current=\"page\">BotkitDialogWrapper</a>\n* <a href=\"#BotkitTestClient\" aria-current=\"page\">BotkitTestClient</a>\n* <a href=\"#TeamsInvokeMiddleware\" aria-current=\"page\">TeamsInvokeMiddleware</a>\n\n## Interfaces\n\n* <a href=\"#BotkitConfiguration\" aria-current=\"page\">BotkitConfiguration</a>\n* <a href=\"#BotkitConversationStep\" aria-current=\"page\">BotkitConversationStep</a>\n* <a href=\"#BotkitHandler\" aria-current=\"page\">BotkitHandler</a>\n* <a href=\"#BotkitMessage\" aria-current=\"page\">BotkitMessage</a>\n* <a href=\"#BotkitPlugin\" aria-current=\"page\">BotkitPlugin</a>\n\n---\n\n<a name=\"Botkit\"></a>\n## Botkit\nCreate a new instance of Botkit to define the controller for a conversational app.\nTo connect Botkit to a chat platform, pass in a fully configured `adapter`.\nIf one is not specified, Botkit will expose an adapter for the Microsoft Bot Framework.\n\nTo use this class in your application, first install the package:\n```bash\nnpm install --save botkit\n```\n\nThen import this and other classes into your code:\n```javascript\nconst { Botkit } = require('botkit');\n```\n\nThis class includes the following methods:\n* [addDep()](#addDep)\n* [addDialog()](#addDialog)\n* [addPluginExtension()](#addPluginExtension)\n* [afterDialog()](#afterDialog)\n* [completeDep()](#completeDep)\n* [getConfig()](#getConfig)\n* [getLocalView()](#getLocalView)\n* [handleTurn()](#handleTurn)\n* [hears()](#hears)\n* [interrupts()](#interrupts)\n* [loadModule()](#loadModule)\n* [loadModules()](#loadModules)\n* [on()](#on)\n* [publicFolder()](#publicFolder)\n* [ready()](#ready)\n* [saveState()](#saveState)\n* [shutdown()](#shutdown)\n* [spawn()](#spawn)\n* [trigger()](#trigger)\n* [usePlugin()](#usePlugin)\n\n\n\n### Create a new Botkit()\n**Parameters**\n\n| Argument | Type | Description\n|--- |--- |---\n| config | [BotkitConfiguration](#BotkitConfiguration) | Configuration for this instance of Botkit<br/>\n\nCreate a new Botkit instance and optionally specify a platform-specific adapter.\nBy default, Botkit will create a [BotFrameworkAdapter](https://docs.microsoft.com/en-us/javascript/api/botbuilder/botframeworkadapter?view=botbuilder-ts-latest).\n\n```javascript\nconst controller = new Botkit({\n     adapter: some_adapter,\n     webhook_uri: '/api/messages',\n});\n\ncontroller.on('message', async(bot, message) => {\n     // do something!\n});\n```\n\n\n\n## Properties and Accessors\n\n| Name | Type | Description\n|--- |--- |---\n| PATH | string | The path of the main Botkit SDK, used to generate relative paths\n| adapter | any | Any BotBuilder-compatible adapter - defaults to a [BotFrameworkAdapter](https://docs.microsoft.com/en-us/javascript/api/botbuilder/botframeworkadapter?view=botbuilder-ts-latest)\n| dialogSet | DialogSet | A BotBuilder DialogSet that serves as the top level dialog container for the Botkit app\n| http | any | A direct reference to the underlying HTTP server object\n| storage | Storage | a BotBuilder storage driver - defaults to MemoryStorage\n| version | string | The current version of Botkit Core\n| webserver | any | An Express webserver\n| plugins |  | Access plugin extension methods.<br/>After a plugin calls `controller.addPluginExtension('foo', extension_methods)`, the extension will then be available at<br/>`controller.plugins.foo`\n\n## Botkit Class Methods\n<a name=\"addDep\"></a>\n### addDep()\n(For use by Botkit plugins only) - Add a dependency to Botkit's bootup process that must be marked as completed using `completeDep()`.\nBotkit's `controller.ready()` function will not fire until all dependencies have been marked complete.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| name| string | The name of the dependency that is being loaded.<br/>\n\n\n\nFor example, a plugin that needs to do an asynchronous task before Botkit proceeds might do:\n```javascript\ncontroller.addDep('my_async_plugin');\nsomethingAsync().then(function() {\n controller.completeDep('my_async_plugin');\n});\n```\n\n\n<a name=\"addDialog\"></a>\n### addDialog()\nAdd a dialog to the bot, making it accessible via `bot.beginDialog(dialog_id)`\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| dialog| Dialog | A dialog to be added to the bot's dialog set<br/>\n\n\n\n```javascript\n// Create a dialog -- `BotkitConversation` is just one way to create a dialog\nconst my_dialog = new BotkitConversation('my_dialog', controller);\nmy_dialog.say('Hello');\n\n// Add the dialog to the Botkit controller\ncontroller.addDialog(my_dialog);\n\n// Later on, trigger the dialog into action!\ncontroller.on('message', async(bot, message) => {\n     await bot.beginDialog('my_dialog');\n});\n```\n\n\n<a name=\"addPluginExtension\"></a>\n### addPluginExtension()\n(Plugins only) Extend Botkit's controller with new functionality and make it available globally via the controller object.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| name| string | name of plugin\n| extension| any | an object containing methods<br/>\n\n\n\n```javascript\n\n// define the extension interface\nlet extension = {\n        stuff: () => { return 'stuff' }\n}\n\n// register the extension\ncontroller.addPluginExtension('foo', extension);\n\n// call extension\ncontroller.plugins.foo.stuff();\n\n\n```\n\n<a name=\"afterDialog\"></a>\n### afterDialog()\nBind a handler to the end of a dialog.\nNOTE: bot worker cannot use bot.reply(), must use bot.send()\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| dialog|  | the dialog object or the id of the dialog\n| handler| [BotkitHandler](#BotkitHandler) | a handler function in the form `async(bot, dialog_results) => {}`<br/>\n\n\n\n[Learn more about handling end-of-conversation](../docs/conversations.md#handling-end-of-conversation)\n\n<a name=\"completeDep\"></a>\n### completeDep()\n(For use by plugins only) - Mark a bootup dependency as loaded and ready to use\nBotkit's `controller.ready()` function will not fire until all dependencies have been marked complete.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| name| string | The name of the dependency that has completed loading.<br/>\n\n\n\n<a name=\"getConfig\"></a>\n### getConfig()\nGet a value from the configuration.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| key (optional)| string | The name of a value stored in the configuration\n\n\n**Returns**\n\nThe value stored in the configuration (or null if absent)\n\n\n\n\nFor example:\n```javascript\n// get entire config object\nlet config = controller.getConfig();\n\n// get a specific value from the config\nlet webhook_uri = controller.getConfig('webhook_uri');\n```\n\n\n<a name=\"getLocalView\"></a>\n### getLocalView()\nConvert a local path from a plugin folder to a full path relative to the webserver's main views folder.\nAllows a plugin to bundle views/layouts and make them available to the webserver's renderer.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| path_to_view| any | something like path.join(__dirname,'views')<br/>\n\n\n\n<a name=\"handleTurn\"></a>\n### handleTurn()\nAccepts the result of a BotBuilder adapter's `processActivity()` method and processes it into a Botkit-style message and BotWorker instance\nwhich is then used to test for triggers and emit events.\nNOTE: This method should only be used in custom adapters that receive messages through mechanisms other than the main webhook endpoint (such as those received via websocket, for example)\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| turnContext| TurnContext | a TurnContext representing an incoming message, typically created by an adapter's `processActivity()` method.<br/>\n\n\n\n<a name=\"hears\"></a>\n### hears()\nInstruct your bot to listen for a pattern, and do something when that pattern is heard.\nPatterns will be \"heard\" only if the message is not already handled by an in-progress dialog.\nTo \"hear\" patterns _before_ dialogs are processed, use `controller.interrupts()` instead.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| patterns|  | One or more string, regular expression, or test function\n| events|  | A list of event types that should be evaluated for the given patterns\n| handler| [BotkitHandler](#BotkitHandler) | a function that will be called should the pattern be matched<br/>\n\n\n\nFor example:\n```javascript\n// listen for a simple keyword\ncontroller.hears('hello','message', async(bot, message) => {\n await bot.reply(message,'I heard you say hello.');\n});\n\n// listen for a regular expression\ncontroller.hears(new RegExp(/^[A-Z\\s]+$/), 'message', async(bot, message) => {\n await bot.reply(message,'I heard a message IN ALL CAPS.');\n});\n\n// listen using a function\ncontroller.hears(async (message) => { return (message.intent === 'hello') }, 'message', async(bot, message) => {\n await bot.reply(message,'This message matches the hello intent.');\n});\n```\n\n<a name=\"interrupts\"></a>\n### interrupts()\nInstruct your bot to listen for a pattern, and do something when that pattern is heard.\nInterruptions work just like \"hears\" triggers, but fire _before_ the dialog system is engaged,\nand thus handlers will interrupt the normal flow of messages through the processing pipeline.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| patterns|  | One or more string, regular expression, or test function\n| events|  | A list of event types that should be evaluated for the given patterns\n| handler| [BotkitHandler](#BotkitHandler) | a function that will be called should the pattern be matched<br/>\n\n\n\n```javascript\ncontroller.interrupts('help','message', async(bot, message) => {\n\n await bot.reply(message,'Before anything else, you need some help!')\n\n});\n```\n\n<a name=\"loadModule\"></a>\n### loadModule()\nLoad a Botkit feature module\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| p| string | path to module file<br/>\n\n\n\n<a name=\"loadModules\"></a>\n### loadModules()\nLoad all Botkit feature modules located in a given folder.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| p| string | path to a folder of module files\n| exts|  | the extensions that you would like to load (default: ['.js'])<br/>\n\n\n\n```javascript\ncontroller.ready(() => {\n\n // load all modules from sub-folder features/\n controller.loadModules('./features');\n\n});\n```\n\n\n<a name=\"on\"></a>\n### on()\nBind a handler function to one or more events.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| events|  | One or more event names\n| handler| [BotkitHandler](#BotkitHandler) | a handler function that will fire whenever one of the named events is received.<br/>\n\n\n\n```javascript\ncontroller.on('conversationUpdate', async(bot, message) => {\n\n await bot.reply(message,'I received a conversationUpdate event.');\n\n});\n```\n\n\n<a name=\"publicFolder\"></a>\n### publicFolder()\nExpose a folder to the web as a set of static files.\nUseful for plugins that need to bundle additional assets!\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| alias| any | the public alias ie /myfiles\n| path| any | the actual path something like `__dirname + '/public'`<br/>\n\n\n\n```javascript\n// make content of the local public folder available at http://MYBOTURL/public/myplugin\ncontroller.publicFolder('/public/myplugin', __dirname + '/public);\n```\n\n<a name=\"ready\"></a>\n### ready()\nUse `controller.ready()` to wrap any calls that require components loaded during the bootup process.\nThis will ensure that the calls will not be made until all of the components have successfully been initialized.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| handler|  | A function to run when Botkit is booted and ready to run.<br/>\n\n\n\nFor example:\n```javascript\ncontroller.ready(() => {\n\n  controller.loadModules(__dirname + '/features');\n\n});\n```\n\n\n<a name=\"saveState\"></a>\n### saveState()\nSave the current conversation state pertaining to a given BotWorker's activities.\nNote: this is normally called internally and is only required when state changes happen outside of the normal processing flow.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| bot| [BotWorker](#BotWorker) | a BotWorker instance created using `controller.spawn()`<br/>\n\n\n\n<a name=\"shutdown\"></a>\n### shutdown()\nShutdown the webserver and prepare to terminate the app.\nCauses Botkit to first emit a special `shutdown` event, process any bound handlers, and then finally terminate the webserver.\nBind any necessary cleanup helpers to the shutdown event - for example, close the connection to mongo.\n\n\n```javascript\nawait controller.shutdown();\ncontroller.on('shutdown', async() => {\n     console.log('Bot is shutting down!');\n});\n```\n\n\n<a name=\"spawn\"></a>\n### spawn()\nCreate a platform-specific BotWorker instance that can be used to respond to messages or generate new outbound messages.\nThe spawned `bot` contains all information required to process outbound messages and handle dialog state, and may also contain extensions\nfor handling platform-specific events or activities.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| config (optional)| any | Preferably receives a DialogContext, though can also receive a TurnContext. If excluded, must call `bot.changeContext(reference)` before calling any other method.\n| custom_adapter (optional)| BotAdapter | \n\n\n\n<a name=\"trigger\"></a>\n### trigger()\nTrigger an event to be fired.  This will cause any bound handlers to be executed.\nNote: This is normally used internally, but can be used to emit custom events.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| event| string | the name of the event\n| bot (optional)| [BotWorker](#BotWorker) | a BotWorker instance created using `controller.spawn()`\n| message (optional)| [BotkitMessage](#BotkitMessage) | An incoming message or event<br/>\n\n\n\n```javascript\n// fire a custom event\ncontroller.trigger('my_custom_event', bot, message);\n\n// handle the custom event\ncontroller.on('my_custom_event', async(bot, message) => {\n //... do something\n});\n```\n\n\n<a name=\"usePlugin\"></a>\n### usePlugin()\nLoad a plugin module and bind all included middlewares to their respective endpoints.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| plugin_or_function|  | A plugin module in the form of function(botkit) {...} that returns {name, middlewares, init} or an object in the same form.<br/>\n\n\n\n\n<a name=\"BotkitBotFrameworkAdapter\"></a>\n## BotkitBotFrameworkAdapter\nThis class extends the [BotFrameworkAdapter](https://docs.microsoft.com/en-us/javascript/api/botbuilder/botframeworkadapter?view=botbuilder-ts-latest) with a few additional features to support Microsoft Teams.\n* Changes userAgent to reflect Botkit instead of BotBuilder\n* Adds getChannels() (MS Teams)\n* Adds middleware for adjusting location of tenant id field (MS Teams)\n\nTo use this class in your application, first install the package:\n```bash\nnpm install --save botkit\n```\n\nThen import this and other classes into your code:\n```javascript\nconst { BotkitBotFrameworkAdapter } = require('botkit');\n```\n\nThis class includes the following methods:\n* [getChannels()](#getChannels)\n\n\n\n\n## Properties and Accessors\n\n| Name | Type | Description\n|--- |--- |---\n| botkit_worker | [TeamsBotWorker](#TeamsBotWorker) | \n\n## BotkitBotFrameworkAdapter Class Methods\n<a name=\"getChannels\"></a>\n### getChannels()\nGet the list of channels in a MS Teams team.\nCan only be called with a TurnContext that originated in a team conversation - 1:1 conversations happen _outside a team_ and thus do not contain the required information to call this API.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| context| TurnContext | A TurnContext object representing a message or event from a user in Teams\n\n\n**Returns**\n\nan array of channels in the format [{name: string, id: string}]\n\n\n\n\n\n<a name=\"TeamsBotWorker\"></a>\n## TeamsBotWorker\nThis is a specialized version of [Botkit's core BotWorker class](core.md#BotWorker) that includes additional methods for interacting with Microsoft Teams.\nIt includes all functionality from the base class, as well as the extension methods below.\nThis BotWorker is used with the built-in Bot Framework adapter.\n\nTo use this class in your application, first install the package:\n```bash\nnpm install --save botkit\n```\n\nThen import this and other classes into your code:\n```javascript\nconst { TeamsBotWorker } = require('botkit');\n```\n\nThis class includes the following methods:\n* [replyWithTaskInfo()](#replyWithTaskInfo)\n\n\n\n\n## Properties and Accessors\n\n| Name | Type | Description\n|--- |--- |---\n| teams | TeamsInfo | Grants access to the TeamsInfo helper class<br/>See: https://docs.microsoft.com/en-us/javascript/api/botbuilder/teamsinfo?view=botbuilder-ts-latest\n\n## TeamsBotWorker Class Methods\n<a name=\"replyWithTaskInfo\"></a>\n### replyWithTaskInfo()\nReply to a Teams task module task/fetch or task/submit with a task module response.\nSee https://docs.microsoft.com/en-us/microsoftteams/platform/task-modules-and-cards/task-modules/task-modules-bots\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| message| [BotkitMessage](#BotkitMessage) | \n| taskInfo| any | an object in the form {type, value}<br/>\n\n\n\n\n<a name=\"BotWorker\"></a>\n## BotWorker\nA base class for a `bot` instance, an object that contains the information and functionality for taking action in response to an incoming message.\nNote that adapters are likely to extend this class with additional platform-specific methods - refer to the adapter documentation for these extensions.\n\nTo use this class in your application, first install the package:\n```bash\nnpm install --save botkit\n```\n\nThen import this and other classes into your code:\n```javascript\nconst { BotWorker } = require('botkit');\n```\n\nThis class includes the following methods:\n* [beginDialog()](#beginDialog)\n* [cancelAllDialogs()](#cancelAllDialogs)\n* [changeContext()](#changeContext)\n* [ensureMessageFormat()](#ensureMessageFormat)\n* [getActiveDialog()](#getActiveDialog)\n* [getConfig()](#getConfig)\n* [hasActiveDialog()](#hasActiveDialog)\n* [httpBody()](#httpBody)\n* [httpStatus()](#httpStatus)\n* [isDialogActive()](#isDialogActive)\n* [replaceDialog()](#replaceDialog)\n* [reply()](#reply)\n* [say()](#say)\n* [startConversationWithUser()](#startConversationWithUser)\n\n\n\n### Create a new BotWorker()\n**Parameters**\n\n| Argument | Type | Description\n|--- |--- |---\n| controller | [Botkit](#Botkit) | A pointer to the main Botkit controller\n| config | any | An object typically containing { dialogContext, reference, context, activity }<br/>\n\nCreate a new BotWorker instance. Do not call this directly - instead, use [controller.spawn()](#spawn).\n\n\n## Properties and Accessors\n\n| Name | Type | Description\n|--- |--- |---\n| controller |  | Get a reference to the main Botkit controller.\n\n## BotWorker Class Methods\n<a name=\"beginDialog\"></a>\n### beginDialog()\nBegin a pre-defined dialog by specifying its id. The dialog will be started in the same context (same user, same channel) in which the original incoming message was received.\n[See \"Using Dialogs\" in the core documentation.](../index.md#using-dialogs)\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| id| string | id of dialog\n| options (optional)| any | object containing options to be passed into the dialog<br/>\n\n\n\n```javascript\ncontroller.hears('hello', 'message', async(bot, message) => {\n     await bot.beginDialog(GREETINGS_DIALOG);\n});\n```\n\n<a name=\"cancelAllDialogs\"></a>\n### cancelAllDialogs()\nCancel any and all active dialogs for the current user/context.\n\n\n<a name=\"changeContext\"></a>\n### changeContext()\nAlter the context in which a bot instance will send messages.\nUse this method to create or adjust a bot instance so that it can send messages to a predefined user/channel combination.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| reference| Partial&lt;ConversationReference&gt; | A [ConversationReference](https://docs.microsoft.com/en-us/javascript/api/botframework-schema/conversationreference?view=botbuilder-ts-latest), most likely captured from an incoming message and stored for use in proactive messaging scenarios.<br/>\n\n\n\n```javascript\n// get the reference field and store it.\nconst saved_reference = message.reference;\n\n// later on...\nlet bot = await controller.spawn();\nbot.changeContext(saved_reference);\nbot.say('Hello!');\n```\n\n\n<a name=\"ensureMessageFormat\"></a>\n### ensureMessageFormat()\nTake a crudely-formed Botkit message with any sort of field (may just be a string, may be a partial message object)\nand map it into a beautiful BotFramework Activity.\nAny fields not found in the Activity definition will be moved to activity.channelData.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| message|  | \n\n\n**Returns**\n\na properly formed Activity object\n\n\n\n\n<a name=\"getActiveDialog\"></a>\n### getActiveDialog()\nGet a reference to the active dialog\n\n**Returns**\n\na reference to the active dialog or undefined if no dialog is active\n\n\n\n\n<a name=\"getConfig\"></a>\n### getConfig()\nGet a value from the BotWorker's configuration.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| key (optional)| string | The name of a value stored in the configuration\n\n\n**Returns**\n\nThe value stored in the configuration (or null if absent)\n\n\n\n\n```javascript\nlet original_context = bot.getConfig('context');\nawait original_context.sendActivity('send directly using the adapter instead of Botkit');\n```\n\n\n<a name=\"hasActiveDialog\"></a>\n### hasActiveDialog()\nCheck if any dialog is active or not\n\n**Returns**\n\ntrue if there is an active dialog, otherwise false\n\n\n\n\n<a name=\"httpBody\"></a>\n### httpBody()\nSet the http response body for this turn.\nUse this to define the response value when the platform requires a synchronous response to the incoming webhook.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| body| any | (any) a value that will be returned as the http response body<br/>\n\n\n\nExample handling of a /slash command from Slack:\n```javascript\ncontroller.on('slash_command', async(bot, message) => {\n bot.httpBody('This is a reply to the slash command.');\n})\n```\n\n\n<a name=\"httpStatus\"></a>\n### httpStatus()\nSet the http response status code for this turn\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| status| number | a valid http status code like 200 202 301 500 etc<br/>\n\n\n\n```javascript\ncontroller.on('event', async(bot, message) => {\n  // respond with a 500 error code for some reason!\n  bot.httpStatus(500);\n});\n```\n\n\n<a name=\"isDialogActive\"></a>\n### isDialogActive()\nCheck to see if a given dialog is currently active in the stack\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| id| string | The id of a dialog to look for in the dialog stack\n\n\n**Returns**\n\ntrue if dialog with id is located anywhere in the dialog stack\n\n\n\n\n<a name=\"replaceDialog\"></a>\n### replaceDialog()\nReplace any active dialogs with a new a pre-defined dialog by specifying its id. The dialog will be started in the same context (same user, same channel) in which the original incoming message was received.\n[See \"Using Dialogs\" in the core documentation.](../index.md#using-dialogs)\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| id| string | id of dialog\n| options (optional)| any | object containing options to be passed into the dialog<br/>\n\n\n\n```javascript\ncontroller.hears('hello', 'message', async(bot, message) => {\n     await bot.replaceDialog(GREETINGS_DIALOG);\n});\n```\n\n<a name=\"reply\"></a>\n### reply()\nReply to an incoming message.\nMessage will be sent using the context of the source message, which may in some cases be different than the context used to spawn the bot.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| src| Partial&lt;BotkitMessage&gt; | An incoming message, usually passed in to a handler function\n| resp|  | A string containing the text of a reply, or more fully formed message object\n\n\n**Returns**\n\nReturn value will contain the results of the send action, typically &#x60;{id: &lt;id of message&gt;}&#x60;\n\n\n\n\nNote that like [bot.say()](#say), `reply()` can take a string or a message object.\n\n```javascript\ncontroller.on('event', async(bot, message) => {\n\n await bot.reply(message, 'I received an event and am replying to it.');\n\n});\n```\n\n\n<a name=\"say\"></a>\n### say()\nSend a message using whatever context the `bot` was spawned in or set using [changeContext()](#changecontext) --\nor more likely, one of the platform-specific helpers like\n[startPrivateConversation()](../reference/slack.md#startprivateconversation) (Slack),\n[startConversationWithUser()](../reference/twilio-sms.md#startconversationwithuser) (Twilio SMS),\nand [startConversationWithUser()](../reference/facebook.md#startconversationwithuser) (Facebook Messenger).\nBe sure to check the platform documentation for others - most adapters include at least one.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| message|  | A string containing the text of a reply, or more fully formed message object\n\n\n**Returns**\n\nReturn value will contain the results of the send action, typically &#x60;{id: &lt;id of message&gt;}&#x60;\n\n\n\n\nSimple use in event handler (acts the same as bot.reply)\n```javascript\ncontroller.on('event', async(bot, message) => {\n\n await bot.say('I received an event!');\n\n});\n```\n\nUse with a freshly spawned bot and bot.changeContext:\n```javascript\nlet bot = controller.spawn(OPTIONS);\nbot.changeContext(REFERENCE);\nbot.say('ALERT! I have some news.');\n```\n\nUse with multi-field message object:\n```javascript\ncontroller.on('event', async(bot, message) => {\n     bot.say({\n         text: 'I heard an event',\n         attachments: [\n             title: message.type,\n             text: `The message was of type ${ message.type }`,\n             // ...\n         ]\n     });\n});\n```\n\n\n<a name=\"startConversationWithUser\"></a>\n### startConversationWithUser()\n\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| reference| any | \n\n\n\n\n<a name=\"BotkitConversation\"></a>\n## BotkitConversation\nAn extension on the [BotBuilder Dialog Class](https://docs.microsoft.com/en-us/javascript/api/botbuilder-dialogs/dialog?view=botbuilder-ts-latest) that provides a Botkit-friendly interface for\ndefining and interacting with multi-message dialogs. Dialogs can be constructed using `say()`, `ask()` and other helper methods.\n\n```javascript\n// define the structure of your dialog...\nconst convo = new BotkitConversation('foo', controller);\nconvo.say('Hello!');\nconvo.ask('What is your name?', async(answer, convo, bot) => {\n     await bot.say('Your name is ' + answer);\n});\ncontroller.dialogSet.add(convo);\n\n// later on, trigger this dialog by its id\ncontroller.on('event', async(bot, message) => {\n await bot.beginDialog('foo');\n})\n```\n\n\nTo use this class in your application, first install the package:\n```bash\nnpm install --save botkit\n```\n\nThen import this and other classes into your code:\n```javascript\nconst { BotkitConversation } = require('botkit');\n```\n\nThis class includes the following methods:\n* [addAction()](#addAction)\n* [addChildDialog()](#addChildDialog)\n* [addGotoDialog()](#addGotoDialog)\n* [addMessage()](#addMessage)\n* [addQuestion()](#addQuestion)\n* [after()](#after)\n* [ask()](#ask)\n* [before()](#before)\n* [onChange()](#onChange)\n* [say()](#say)\n\n\n\n### Create a new BotkitConversation()\n**Parameters**\n\n| Argument | Type | Description\n|--- |--- |---\n| dialogId | string | A unique identifier for this dialog, used to later trigger this dialog\n| controller | [Botkit](#Botkit) | A pointer to the main Botkit controller<br/>\n\nCreate a new BotkitConversation object\n\n\n## Properties and Accessors\n\n| Name | Type | Description\n|--- |--- |---\n| script | any | A map of every message in the dialog, broken into threads\n\n## BotkitConversation Class Methods\n<a name=\"addAction\"></a>\n### addAction()\nAn an action to the conversation timeline. This can be used to go to switch threads or end the dialog.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| action| string | An action or thread name\n| thread_name| string | The name of the thread to which this action is added.  Defaults to `default`<br/>\n\n\n\nWhen provided the name of another thread in the conversation, this will cause the bot to go immediately\nto that thread.\n\nOtherwise, use one of the following keywords:\n* `stop`\n* `repeat`\n* `complete`\n* `timeout`\n\n[Learn more about building conversations &rarr;](../conversations.md#build-a-conversation)\n\n```javascript\n\n// go to a thread called \"next_thread\"\nconvo.addAction('next_thread');\n\n// end the conversation and mark as successful\nconvo.addAction('complete');\n```\n\n<a name=\"addChildDialog\"></a>\n### addChildDialog()\nCause the dialog to call a child dialog, wait for it to complete,\nthen store the results in a variable and resume the parent dialog.\nUse this to [combine multiple dialogs into bigger interactions.](../conversations.md#composing-dialogs)\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| dialog_id| string | the id of another dialog\n| key_name (optional)| string | the variable name in which to store the results of the child dialog. if not provided, defaults to dialog_id.\n| thread_name| string | the name of a thread to which this call should be added. defaults to 'default'<br/>\n\n\n\n[Learn more about building conversations &rarr;](../conversations.md#build-a-conversation)\n```javascript\n// define a profile collection dialog\nlet profileDialog = new BotkitConversation('PROFILE_DIALOG', controller);\nprofileDialog.ask('What is your name?', async(res, convo, bot) => {}, {key: 'name'});\nprofileDialog.ask('What is your age?', async(res, convo, bot) => {}, {key: 'age'});\nprofileDialog.ask('What is your location?', async(res, convo, bot) => {}, {key: 'location'});\ncontroller.addDialog(profileDialog);\n\nlet onboard = new BotkitConversation('ONBOARDING', controller);\nonboard.say('Hello! It is time to collect your profile data.');\nonboard.addChildDialog('PROFILE_DIALOG', 'profile');\nonboard.say('Hello, {{vars.profile.name}}! Onboarding is complete.');\n```\n\n\n<a name=\"addGotoDialog\"></a>\n### addGotoDialog()\nCause the current dialog to handoff to another dialog.\nThe parent dialog will not resume when the child dialog completes. However, the afterDialog event will not fire for the parent dialog until all child dialogs complete.\nUse this to [combine multiple dialogs into bigger interactions.](../conversations.md#composing-dialogs)\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| dialog_id| string | the id of another dialog\n| thread_name| string | the name of a thread to which this call should be added. defaults to 'default'<br/>\n\n\n\n[Learn more about building conversations &rarr;](../conversations.md#build-a-conversation)\n```javascript\nlet parent = new BotkitConversation('parent', controller);\nlet child = new BotkitConversation('child', controller);\nparent.say('Moving on....');\nparent.addGotoDialog('child');\n```\n\n\n<a name=\"addMessage\"></a>\n### addMessage()\nAdd a message template to a specific thread.\nMessages added with `say()` and `addMessage()` will be sent one after another without a pause.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| message|  | Message template to be sent\n| thread_name| string | Name of thread to which message will be added<br/>\n\n\n\n[Learn more about building conversations &rarr;](../conversations.md#build-a-conversation)\n```javascript\nlet conversation = new BotkitConversation('welcome', controller);\nconversation.say('Hello! Welcome to my app.');\nconversation.say('Let us get started...');\n// pass in a message with an action that will cause gotoThread to be called...\nconversation.addAction('continuation');\n\nconversation.addMessage('This is a different thread completely', 'continuation');\n```\n\n\n<a name=\"addQuestion\"></a>\n### addQuestion()\nIdentical to [ask()](#ask), but accepts the name of a thread to which the question is added.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| message|  | A message that will be used as the prompt\n| handlers|  | One or more handler functions defining possible conditional actions based on the response to the question\n| key|  | Name of variable to store response in.\n| thread_name| string | Name of thread to which message will be added<br/>\n\n\n\n[Learn more about building conversations &rarr;](../conversations.md#build-a-conversation)\n\n<a name=\"after\"></a>\n### after()\nBind a function to run after the dialog has completed.\nThe first parameter to the handler will include a hash of all variables set and values collected from the user during the conversation.\nThe second parameter to the handler is a BotWorker object that can be used to start new dialogs or take other actions.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| handler|  | in the form async(results, bot) { ... }<br/>\n\n\n\n[Learn more about handling end of conversation](../conversations.md#handling-end-of-conversation)\n```javascript\nlet convo = new BotkitConversation(MY_CONVO, controller);\nconvo.ask('What is your name?', [], 'name');\nconvo.ask('What is your age?', [], 'age');\nconvo.ask('What is your favorite color?', [], 'color');\nconvo.after(async(results, bot) => {\n\n     // handle results.name, results.age, results.color\n\n});\ncontroller.addDialog(convo);\n```\n\n\n<a name=\"ask\"></a>\n### ask()\nAdd a question to the default thread.\nIn addition to a message template, receives either a single handler function to call when an answer is provided,\nor an array of handlers paired with trigger patterns. When providing multiple conditions to test, developers may also provide a\nhandler marked as the default choice.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| message|  | a message that will be used as the prompt\n| handlers|  | one or more handler functions defining possible conditional actions based on the response to the question.\n| key|  | name of variable to store response in.<br/>\n\n\n\n[Learn more about building conversations &rarr;](../conversations.md#build-a-conversation)\n```javascript\n// ask a question, handle the response with a function\nconvo.ask('What is your name?', async(response, convo, bot, full_message) => {\n await bot.say('Oh your name is ' + response);\n}, {key: 'name'});\n\n// ask a question, evaluate answer, take conditional action based on response\nconvo.ask('Do you want to eat a taco?', [\n {\n     pattern: 'yes',\n     type: 'string',\n     handler: async(response_text, convo, bot, full_message) => {\n         return await convo.gotoThread('yes_taco');\n     }\n },\n {\n     pattern: 'no',\n     type: 'string',\n     handler: async(response_text, convo, bot, full_message) => {\n         return await convo.gotoThread('no_taco');\n     }\n  },\n  {\n      default: true,\n      handler: async(response_text, convo, bot, full_message) => {\n          await bot.say('I do not understand your response!');\n          // start over!\n          return await convo.repeat();\n      }\n  }\n], {key: 'tacos'});\n```\n\n\n<a name=\"before\"></a>\n### before()\nRegister a handler function that will fire before a given thread begins.\nUse this hook to set variables, call APIs, or change the flow of the conversation using `convo.gotoThread`\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| thread_name| string | A valid thread defined in this conversation\n| handler|  | A handler function in the form async(convo, bot) => { ... }<br/>\n\n\n\n```javascript\nconvo.addMessage('This is the foo thread: var == {{vars.foo}}', 'foo');\nconvo.before('foo', async(convo, bot) => {\n // set a variable here that can be used in the message template\n convo.setVar('foo','THIS IS FOO');\n\n});\n```\n\n\n<a name=\"onChange\"></a>\n### onChange()\nBind a function to run whenever a user answers a specific question.  Can be used to validate input and take conditional actions.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| variable| string | name of the variable to watch for changes\n| handler|  | a handler function that will fire whenever a user's response is used to change the value of the watched variable<br/>\n\n\n\n```javascript\nconvo.ask('What is your name?', [], 'name');\nconvo.onChange('name', async(response, convo, bot) => {\n\n // user changed their name!\n // do something...\n\n});\n```\n\n<a name=\"say\"></a>\n### say()\nAdd a non-interactive message to the default thread.\nMessages added with `say()` and `addMessage()` will _not_ wait for a response, will be sent one after another without a pause.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| message|  | Message template to be sent<br/>\n\n\n\n[Learn more about building conversations &rarr;](../conversations.md#build-a-conversation)\n\n```javascript\nlet conversation = new BotkitConversation('welcome', controller);\nconversation.say('Hello! Welcome to my app.');\nconversation.say('Let us get started...');\n```\n\n\n\n<a name=\"BotkitDialogWrapper\"></a>\n## BotkitDialogWrapper\nThis class is used to provide easy access to common actions taken on active BotkitConversation instances.\nThese objects are passed into handlers bound to BotkitConversations using .before .onChange and conditional handler functions passed to .ask and .addQuestion\nGrants access to convo.vars convo.gotoThread() convo.setVar() and convo.repeat().\n\nTo use this class in your application, first install the package:\n```bash\nnpm install --save botkit\n```\n\nThen import this and other classes into your code:\n```javascript\nconst { BotkitDialogWrapper } = require('botkit');\n```\n\nThis class includes the following methods:\n* [gotoThread()](#gotoThread)\n* [repeat()](#repeat)\n* [setVar()](#setVar)\n* [stop()](#stop)\n\n\n\n### Create a new BotkitDialogWrapper()\n**Parameters**\n\n| Argument | Type | Description\n|--- |--- |---\n| dc | DialogContext | \n| step | [BotkitConversationStep](#BotkitConversationStep) | \n\n\n\n\n## Properties and Accessors\n\n| Name | Type | Description\n|--- |--- |---\n| vars |  | An object containing variables and user responses from this conversation.\n\n## BotkitDialogWrapper Class Methods\n<a name=\"gotoThread\"></a>\n### gotoThread()\nJump immediately to the first message in a different thread.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| thread| string | Name of a thread<br/>\n\n\n\n<a name=\"repeat\"></a>\n### repeat()\nRepeat the last message sent on the next turn.\n\n\n<a name=\"setVar\"></a>\n### setVar()\nSet the value of a variable that will be available to messages in the conversation.\nEquivalent to convo.vars.key = val;\nResults in {{vars.key}} being replaced with the value in val.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| key| any | the name of the variable\n| val| any | the value for the variable<br/>\n\n\n\n<a name=\"stop\"></a>\n### stop()\nStop the dialog.\n\n\n\n<a name=\"BotkitTestClient\"></a>\n## BotkitTestClient\nA client for testing dialogs in isolation.\n\nTo use this class in your application, first install the package:\n```bash\nnpm install --save botkit\n```\n\nThen import this and other classes into your code:\n```javascript\nconst { BotkitTestClient } = require('botkit');\n```\n\nThis class includes the following methods:\n* [getNextReply()](#getNextReply)\n* [sendActivity()](#sendActivity)\n\n\n\n### Create a new BotkitTestClient()\n**Parameters**\n\n| Argument | Type | Description\n|--- |--- |---\n| channelId | string | The channelId to be used for the test.<br/>Use 'emulator' or 'test' if you are uncertain of the channel you are targeting.<br/>Otherwise, it is recommended that you use the id for the channel(s) your bot will be using and write a test case for each channel.\n| bot | [Botkit](#Botkit) | (Required) The Botkit bot that has the skill to test.\n| dialogToTest |  | (Required) The identifier of the skill to test in the bot.\n| initialDialogOptions | any | (Optional) additional argument(s) to pass to the dialog being started.\n| middlewares |  | (Optional) a stack of middleware to be run when testing\n| conversationState | ConversationState | (Optional) A ConversationState instance to use in the test client<br/>\n\nCreate a BotkitTestClient to test a dialog without having to create a full-fledged adapter.\n\n```javascript\nlet client = new BotkitTestClient('test', bot, MY_DIALOG, MY_OPTIONS);\nlet reply = await client.sendActivity('first message');\nassert.strictEqual(reply.text, 'first reply', 'reply failed');\n```\n\n\n### Create a new BotkitTestClient()\n**Parameters**\n\n| Argument | Type | Description\n|--- |--- |---\n| testAdapter | TestAdapter | \n| bot | [Botkit](#Botkit) | (Required) The Botkit bot that has the skill to test.\n| dialogToTest |  | (Required) The identifier of the skill to test in the bot.\n| initialDialogOptions | any | (Optional) additional argument(s) to pass to the dialog being started.\n| middlewares |  | (Optional) a stack of middleware to be run when testing\n| conversationState | ConversationState | (Optional) A ConversationState instance to use in the test client<br/>\n\nCreate a BotkitTestClient to test a dialog without having to create a full-fledged adapter.\n\n```javascript\nlet client = new BotkitTestClient('test', bot, MY_DIALOG, MY_OPTIONS);\nlet reply = await client.sendActivity('first message');\nassert.strictEqual(reply.text, 'first reply', 'reply failed');\n```\n\n\n\n## Properties and Accessors\n\n| Name | Type | Description\n|--- |--- |---\n| conversationState | ConversationState | \n| dialogTurnResult | DialogTurnResult | \n\n## BotkitTestClient Class Methods\n<a name=\"getNextReply\"></a>\n### getNextReply()\nGet the next reply waiting to be delivered (if one exists)\n\n\n<a name=\"sendActivity\"></a>\n### sendActivity()\nSend an activity into the dialog.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| activity|  | an activity potentially with text<br/><br/>```javascript<br/>DialogTest.send('hello').assertReply('hello yourself').then(done);<br/>```<br/>\n\n\n**Returns**\n\na TestFlow that can be used to assert replies etc\n\n\n\n\n<a name=\"TeamsInvokeMiddleware\"></a>\n## TeamsInvokeMiddleware\nWhen used, causes Botkit to emit special events for teams \"invokes\"\nBased on https://github.com/microsoft/botbuilder-js/blob/master/libraries/botbuilder/src/teamsActivityHandler.ts\nThis allows Botkit bots to respond directly to task/fetch or task/submit events, as an example.\nTo use this, bind it to the adapter before creating the Botkit controller:\n```javascript\nconst Botkit = new Botkit({...});\nbotkit.adapter.use(new TeamsInvokeMiddleware());\n\n// can bind directly to task/fetch, task/submit and other invoke types used by teams\ncontroller.on('task/fetch', async(bot, message) => {\n   await bot.replyWithTaskInfo(message, taskInfo);\n});\n```\n\n\nTo use this class in your application, first install the package:\n```bash\nnpm install --save botkit\n```\n\nThen import this and other classes into your code:\n```javascript\nconst { TeamsInvokeMiddleware } = require('botkit');\n```\n\nThis class includes the following methods:\n* [onTurn()](#onTurn)\n\n\n\n\n\n## TeamsInvokeMiddleware Class Methods\n<a name=\"onTurn\"></a>\n### onTurn()\nNot for direct use - implements the MiddlewareSet's required onTurn function used to process the event\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| context| TurnContext | \n| next|  | <br/>\n\n\n\n\n\n<a name=\"BotkitConfiguration\"></a>\n## Interface BotkitConfiguration\nDefines the options used when instantiating Botkit to create the main app controller with `new Botkit(options)`\n\n**Fields**\n\n| Name | Type | Description\n|--- |--- |---\n| adapter | any | A fully configured BotBuilder Adapter, such as `botbuilder-adapter-slack` or `botbuilder-adapter-web`<br/>The adapter is responsible for translating platform-specific messages into the format understood by Botkit and BotBuilder.<br/>\n| adapterConfig |  | If using the BotFramework service, options included in `adapterConfig` will be passed to the new Adapter when created internally.<br/>See [BotFrameworkAdapterSettings](https://docs.microsoft.com/en-us/javascript/api/botbuilder/botframeworkadaptersettings?view=azure-node-latest&viewFallbackFrom=botbuilder-ts-latest).<br/>\n| dialogStateProperty | string | Name of the dialogState property in the ConversationState that will be used to automatically track the dialog state. Defaults to `dialogState`.<br/>\n| disable_console | boolean | Disable messages normally sent to the console during startup.<br/>\n| disable_webserver | boolean | Disable webserver. If true, Botkit will not create a webserver or expose any webhook endpoints automatically. Defaults to false.<br/>For an example of how to use your own Express, [see this sample code](https://github.com/howdyai/botkit/blob/main/packages/testbot/custom_express.js).\n\n| jsonLimit | string | Limit of the size of incoming JSON payloads parsed by the Express bodyParser. Defaults to '100kb'<br/>\n| storage | Storage | A Storage interface compatible with [this specification](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/storage?view=botbuilder-ts-latest)<br/>Defaults to the ephemeral [MemoryStorage](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/memorystorage?view=botbuilder-ts-latest) implementation.<br/>\n| urlEncodedLimit | string | Limit of the size of incoming URL encoded payloads parsed by the Express bodyParser. Defaults to '100kb'<br/>\n| webhook_uri | string | Path used to create incoming webhook URI.  Defaults to `/api/messages`<br/>\n| webserver | any | An instance of Express used to define web endpoints.  If not specified, one will be created internally.<br/>Note: only use your own Express if you absolutely must for some reason. Otherwise, use `controller.webserver`<br/>\n| webserver_middlewares |  | An array of middlewares that will be automatically bound to the webserver.<br/>Should be in the form (req, res, next) => {}<br/>\n<a name=\"BotkitConversationStep\"></a>\n## Interface BotkitConversationStep\n\n\n**Fields**\n\n| Name | Type | Description\n|--- |--- |---\n| index | number | The number pointing to the current message in the current thread in this dialog's script<br/>\n| next |  | A function to call when the step is completed.<br/>\n| options | any | A pointer to any options passed into the dialog when it began<br/>\n| reason | DialogReason | The reason for this step being called<br/>\n| result | any | The results of the previous turn<br/>\n| state | any | A pointer to the current dialog state<br/>\n| thread | string | The name of the current thread<br/>\n| threadLength | number | The length of the current thread<br/>\n| values | any | A pointer directly to state.values<br/>\n<a name=\"BotkitHandler\"></a>\n## Interface BotkitHandler\nA handler function passed into `hears()` or `on()` that receives a [BotWorker](#botworker) instance and a [BotkitMessage](#botkitmessage).  Should be defined as an async function and/or return a Promise.\n\nThe form of these handlers should be:\n```javascript\nasync (bot, message) => {\n// stuff.\n}\n```\n\nFor example:\n```javascript\ncontroller.on('event', async(bot, message) => {\n // do somethign using bot and message like...\n await bot.reply(message,'Received an event.');\n});\n```\n\n\n<a name=\"BotkitMessage\"></a>\n## Interface BotkitMessage\nDefines the expected form of a message or event object being handled by Botkit.\nWill also contain any additional fields including in the incoming payload.\n\n**Fields**\n\n| Name | Type | Description\n|--- |--- |---\n| channel | string | Unique identifier of the room/channel/space in which the message was sent. Typically contains the platform specific designator for that channel.<br/>\n| incoming_message | Activity | The original incoming [BotBuilder Activity](https://docs.microsoft.com/en-us/javascript/api/botframework-schema/activity?view=botbuilder-ts-latest) object as created by the adapter.<br/>\n| reference | ConversationReference | A full [ConversationReference](https://docs.microsoft.com/en-us/javascript/api/botframework-schema/conversationreference?view=botbuilder-ts-latest) object that defines the address of the message and all information necessary to send messages back to the originating location.<br/>Can be stored for later use, and used with [bot.changeContext()](#changeContext) to send proactive messages.<br/>\n| text | string | Text of the message sent by the user (or primary value in case of button click)<br/>\n| type | string | The type of event, in most cases defined by the messaging channel or adapter<br/>\n| user | string | Unique identifier of user who sent the message. Typically contains the platform specific user id.<br/>\n| value | string | Any value field received from the platform<br/>\n<a name=\"BotkitPlugin\"></a>\n## Interface BotkitPlugin\nAn interface for plugins that can contain multiple middlewares as well as an init function.\n\n**Fields**\n\n| Name | Type | Description\n|--- |--- |---\n| init |  | \n| middlewares |  | \n| name | string | \n"
  },
  {
    "path": "packages/docs/reference/facebook.md",
    "content": "# Botkit for Facebook Class Reference\n\n[&larr; Botkit Documentation](../core.md) [&larr; Class Index](index.md) \n\nThis is a class reference for all the methods exposed by the [botbuilder-adapter-facebook](https://github.com/howdyai/botkit/tree/master/packages/botbuilder-adapter-facebook) package.\n\n## Classes\n\n\n* <a href=\"#FacebookAdapter\" aria-current=\"page\">FacebookAdapter</a>\n* <a href=\"#FacebookBotWorker\" aria-current=\"page\">FacebookBotWorker</a>\n* <a href=\"#FacebookAPI\" aria-current=\"page\">FacebookAPI</a>\n* <a href=\"#FacebookEventTypeMiddleware\" aria-current=\"page\">FacebookEventTypeMiddleware</a>\n\n## Interfaces\n\n* <a href=\"#FacebookAdapterOptions\" aria-current=\"page\">FacebookAdapterOptions</a>\n\n---\n\n<a name=\"FacebookAdapter\"></a>\n## FacebookAdapter\nConnect [Botkit](https://www.npmjs.com/package/botkit) or [BotBuilder](https://www.npmjs.com/package/botbuilder) to Facebook Messenger.\n\nTo use this class in your application, first install the package:\n```bash\nnpm install --save botbuilder-adapter-facebook\n```\n\nThen import this and other classes into your code:\n```javascript\nconst { FacebookAdapter } = require('botbuilder-adapter-facebook');\n```\n\nThis class includes the following methods:\n* [continueConversation()](#continueConversation)\n* [getAPI()](#getAPI)\n* [init()](#init)\n* [processActivity()](#processActivity)\n* [sendActivities()](#sendActivities)\n\n\n\n### Create a new FacebookAdapter()\n**Parameters**\n\n| Argument | Type | Description\n|--- |--- |---\n| options | [FacebookAdapterOptions](#FacebookAdapterOptions) | Configuration options<br/>\n\nCreate an adapter to handle incoming messages from Facebook and translate them into a standard format for processing by your bot.\n\nThe Facebook Adapter can be used in 2 modes:\n* bound to a single Facebook page\n* multi-tenancy mode able to serve multiple pages\n\nTo create an app bound to a single Facebook page, include that page's `access_token` in the options.\n\nTo create an app that can be bound to multiple pages, include `getAccessTokenForPage` - a function in the form `async (pageId) => page_access_token`\n\nTo use with Botkit:\n```javascript\nconst adapter = new FacebookAdapter({\n     verify_token: process.env.FACEBOOK_VERIFY_TOKEN,\n     app_secret: process.env.FACEBOOK_APP_SECRET,\n     access_token: process.env.FACEBOOK_ACCESS_TOKEN\n});\nconst controller = new Botkit({\n     adapter: adapter,\n     // other options\n});\n```\n\nTo use with BotBuilder:\n```javascript\nconst adapter = new FacebookAdapter({\n     verify_token: process.env.FACEBOOK_VERIFY_TOKEN,\n     app_secret: process.env.FACEBOOK_APP_SECRET,\n     access_token: process.env.FACEBOOK_ACCESS_TOKEN\n});\nconst server = restify.createServer();\nserver.use(restify.plugins.bodyParser());\nserver.post('/api/messages', (req, res) => {\n     adapter.processActivity(req, res, async(context) => {\n         // do your bot logic here!\n     });\n});\n```\n\nIn multi-tenancy mode:\n```javascript\nconst adapter = new FacebookAdapter({\n     verify_token: process.env.FACEBOOK_VERIFY_TOKEN,\n     app_secret: process.env.FACEBOOK_APP_SECRET,\n      getAccessTokenForPage: async(pageId) => {\n          // do something to fetch the page access token for pageId.\n          return token;\n      })\n});\n```\n\n\n\n\n## FacebookAdapter Class Methods\n<a name=\"continueConversation\"></a>\n### continueConversation()\nStandard BotBuilder adapter method for continuing an existing conversation based on a conversation reference.\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#continueconversation)\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| reference| Partial&lt;ConversationReference&gt; | A conversation reference to be applied to future messages.\n| logic|  | A bot logic function that will perform continuing action in the form `async(context) => { ... }`<br/>\n\n\n\n<a name=\"getAPI\"></a>\n### getAPI()\nGet a Facebook API client with the correct credentials based on the page identified in the incoming activity.\nThis is used by many internal functions to get access to the Facebook API, and is exposed as `bot.api` on any BotWorker instances passed into Botkit handler functions.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| activity| Partial&lt;Activity&gt; | An incoming message activity<br/>\n\n\n\n```javascript\nlet api = adapter.getAPI(activity);\nlet res = api.callAPI('/me/messages', 'POST', message);\n```\n\n<a name=\"init\"></a>\n### init()\nBotkit-only: Initialization function called automatically when used with Botkit.\n     * Amends the webhook_uri with an additional behavior for responding to Facebook's webhook verification request.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| botkit| any | <br/>\n\n\n\n<a name=\"processActivity\"></a>\n### processActivity()\nAccept an incoming webhook request and convert it into a TurnContext which can be processed by the bot's logic.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| req| any | A request object from Restify or Express\n| res| any | A response object from Restify or Express\n| logic|  | A bot logic function in the form `async(context) => { ... }`<br/>\n\n\n\n<a name=\"sendActivities\"></a>\n### sendActivities()\nStandard BotBuilder adapter method to send a message from the bot to the messaging API.\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#sendactivities).\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| context| TurnContext | A TurnContext representing the current incoming message and environment.\n| activities|  | An array of outgoing activities to be sent back to the messaging API.<br/>\n\n\n\n\n<a name=\"FacebookBotWorker\"></a>\n## FacebookBotWorker\nThis is a specialized version of [Botkit's core BotWorker class](core.md#BotWorker) that includes additional methods for interacting with Facebook.\nIt includes all functionality from the base class, as well as the extension methods below.\n\nWhen using the FacebookAdapter with Botkit, all `bot` objects passed to handler functions will include these extensions.\n\n\nTo use this class in your application, first install the package:\n```bash\nnpm install --save botbuilder-adapter-facebook\n```\n\nThen import this and other classes into your code:\n```javascript\nconst { FacebookBotWorker } = require('botbuilder-adapter-facebook');\n```\n\nThis class includes the following methods:\n* [startConversationWithUser()](#startConversationWithUser)\n\n\n\n### Create a new FacebookBotWorker()\n**Parameters**\n\n| Argument | Type | Description\n|--- |--- |---\n| botkit | Botkit | The Botkit controller object responsible for spawning this bot worker.\n| config | any | Normally, a DialogContext object.  Can also be the ID of a Facebook page managed by this app.<br/>\n\nReserved for use internally by Botkit's `controller.spawn()`, this class is used to create a BotWorker instance that can send messages, replies, and make other API calls.\n\nWhen used with the FacebookAdapter's multi-tenancy mode, it is possible to spawn a bot instance by passing in the Facebook page ID representing the appropriate bot identity.\nUse this in concert with [startConversationWithUser()](#startConversationWithUser) and [changeContext()](core.md#changecontext) to start conversations\nor send proactive alerts to users on a schedule or in response to external events.\n\n```javascript\nlet bot = await controller.spawn(FACEBOOK_PAGE_ID);\n```\n\n\n## Properties and Accessors\n\n| Name | Type | Description\n|--- |--- |---\n| api | [FacebookAPI](#FacebookAPI) | A copy of the FacebookAPI client giving access to `let res = await bot.api.callAPI(path, method, parameters);`\n\n## FacebookBotWorker Class Methods\n<a name=\"startConversationWithUser\"></a>\n### startConversationWithUser()\nChange the operating context of the worker to begin a conversation with a specific user.\nAfter calling this method, any calls to `bot.say()` or `bot.beginDialog()` will occur in this new context.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| userId| any | the PSID of a user the bot has previously interacted with<br/>\n\n\n\nThis method can be used to send users scheduled messages or messages triggered by external events.\n```javascript\nlet bot = await controller.spawn(FACEBOOK_PAGE_ID);\nawait bot.startConversationWithUser(FACEBOOK_USER_PSID);\nawait bot.say('Howdy human!');\n```\n\n\n\n<a name=\"FacebookAPI\"></a>\n## FacebookAPI\nA simple API client for the Facebook API.  Automatically signs requests with the access token and app secret proof.\nIt can be used to call any API provided by Facebook.\n\nTo use this class in your application, first install the package:\n```bash\nnpm install --save botbuilder-adapter-facebook\n```\n\nThen import this and other classes into your code:\n```javascript\nconst { FacebookAPI } = require('botbuilder-adapter-facebook');\n```\n\nThis class includes the following methods:\n* [callAPI()](#callAPI)\n\n\n\n### Create a new FacebookAPI()\n**Parameters**\n\n| Argument | Type | Description\n|--- |--- |---\n| token | string | a page access token\n| secret | string | an app secret\n| api_host | string | optional root hostname for constructing api calls, defaults to graph.facebook.com\n| api_version | string | optional api version used when constructing api calls, defaults to v3.2<br/>\n\nCreate a FacebookAPI client.\n```\nlet api = new FacebookAPI(TOKEN, SECRET);\nawait api.callAPI('/some/api','POST', {some_options});\n```\n\n\n\n## FacebookAPI Class Methods\n<a name=\"callAPI\"></a>\n### callAPI()\nCall one of the Facebook APIs\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| path| string | Path to the API endpoint, for example `/me/messages`\n| method| string | HTTP method, for example POST, GET, DELETE or PUT.\n| payload| any | An object to be sent as parameters to the API call.<br/>\n\n\n\n\n<a name=\"FacebookEventTypeMiddleware\"></a>\n## FacebookEventTypeMiddleware\nThis adapter middleware, when used in conjunction with FacebookAdapter and Botkit, will result in Botkit emitting events with\nnames based on their event type.\n\n```javascript\nconst adapter = new FacebookAdapter(MY_OPTIONS);\nadapter.use(new FacebookEventTypeMiddleware());\nconst controller = new Botkit({\n     adapter: adapter,\n});\n\n// define a handler for one of the new events\ncontroller.on('facebook_option', async(bot, message) => {\n     // ...\n});\n```\n\nWhen used, events emitted may include:\n* facebook_postback\n* facebook_referral\n* facebook_optin\n* message_delivered\n* message_read\n* facebook_account_linking\n* message_echo\n* facebook_app_roles\n* standby\n* facebook_receive_thread_control\n* facebook_request_thread_control\n\n\n\nTo use this class in your application, first install the package:\n```bash\nnpm install --save botbuilder-adapter-facebook\n```\n\nThen import this and other classes into your code:\n```javascript\nconst { FacebookEventTypeMiddleware } = require('botbuilder-adapter-facebook');\n```\n\n\n\n\n\n\n\n\n<a name=\"FacebookAdapterOptions\"></a>\n## Interface FacebookAdapterOptions\nThis interface defines the options that can be passed into the FacebookAdapter constructor function.\n\n**Fields**\n\n| Name | Type | Description\n|--- |--- |---\n| access_token | string | When bound to a single page, use `access_token` to specify the \"page access token\" provided in the Facebook developer portal's \"Access Tokens\" widget of the \"Messenger Settings\" page.<br/>\n| api_host | string | Alternate root url used to contruct calls to Facebook's API.  Defaults to 'graph.facebook.com' but can be changed (for mocking, proxy, etc).<br/>\n| api_version | string | Alternate API version used to construct calls to Facebook's API. Defaults to v3.2<br/>\n| app_secret | string | The \"app secret\" from the \"basic settings\" page from your app's configuration in the Facebook developer portal<br/>\n| enable_incomplete | boolean | Allow the adapter to startup without a complete configuration.<br/>This is risky as it may result in a non-functioning or insecure adapter.<br/>This should only be used when getting started.<br/>\n| getAccessTokenForPage |  | When bound to multiple teams, provide a function that, given a page id, will return the page access token for that page.<br/>\n| verify_token | string | The \"verify token\" used to initially create and verify the Webhooks subscription settings on Facebook's developer portal.<br/>\n"
  },
  {
    "path": "packages/docs/reference/hangouts.md",
    "content": "# Botkit for Hangouts Class Reference\n\n[&larr; Botkit Documentation](../core.md) [&larr; Class Index](index.md) \n\nThis is a class reference for all the methods exposed by the [botbuilder-adapter-hangouts](https://github.com/howdyai/botkit/tree/master/packages/botbuilder-adapter-hangouts) package.\n\n## Classes\n\n\n* <a href=\"#HangoutsAdapter\" aria-current=\"page\">HangoutsAdapter</a>\n* <a href=\"#HangoutsBotWorker\" aria-current=\"page\">HangoutsBotWorker</a>\n\n## Interfaces\n\n* <a href=\"#HangoutsAdapterOptions\" aria-current=\"page\">HangoutsAdapterOptions</a>\n\n---\n\n<a name=\"HangoutsAdapter\"></a>\n## HangoutsAdapter\nConnect [Botkit](https://www.npmjs.com/package/botkit) or [BotBuilder](https://www.npmjs.com/package/botbuilder) to Google Hangouts\n\nTo use this class in your application, first install the package:\n```bash\nnpm install --save botbuilder-adapter-hangouts\n```\n\nThen import this and other classes into your code:\n```javascript\nconst { HangoutsAdapter } = require('botbuilder-adapter-hangouts');\n```\n\nThis class includes the following methods:\n* [continueConversation()](#continueConversation)\n* [deleteActivity()](#deleteActivity)\n* [processActivity()](#processActivity)\n* [sendActivities()](#sendActivities)\n* [updateActivity()](#updateActivity)\n\n\n\n### Create a new HangoutsAdapter()\n**Parameters**\n\n| Argument | Type | Description\n|--- |--- |---\n| options | [HangoutsAdapterOptions](#HangoutsAdapterOptions) | An object containing API credentials and a webhook verification token<br/>\n\nCreate an adapter to handle incoming messages from Google Hangouts and translate them into a standard format for processing by your bot.\n\nUse with Botkit:\n```javascript\nconst adapter = new HangoutsAdapter({\n     token: process.env.GOOGLE_TOKEN,\n     google_auth_params: {\n         credentials: process.env.GOOGLE_CREDS\n     }\n});\nconst controller = new Botkit({\n     adapter: adapter,\n     // ... other configuration options\n});\n```\n\nUse with BotBuilder:\n```javascript\nconst adapter = new HangoutsAdapter({\n     token: process.env.GOOGLE_TOKEN,\n     google_auth_params: {\n         credentials: process.env.GOOGLE_CREDS\n     }\n});\n// set up restify...\nconst server = restify.createServer();\nserver.use(restify.plugins.bodyParser());\nserver.post('/api/messages', (req, res) => {\n     adapter.processActivity(req, res, async(context) => {\n         // do your bot logic here!\n     });\n});\n```\n\n\n\n\n## HangoutsAdapter Class Methods\n<a name=\"continueConversation\"></a>\n### continueConversation()\nStandard BotBuilder adapter method for continuing an existing conversation based on a conversation reference.\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#continueconversation)\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| reference| Partial&lt;ConversationReference&gt; | A conversation reference to be applied to future messages.\n| logic|  | A bot logic function that will perform continuing action in the form `async(context) => { ... }`<br/>\n\n\n\n<a name=\"deleteActivity\"></a>\n### deleteActivity()\nStandard BotBuilder adapter method to delete a previous message.\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#deleteactivity).\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| context| TurnContext | A TurnContext representing the current incoming message and environment. (Not used)\n| reference| Partial&lt;ConversationReference&gt; | An object in the form `{activityId: <id of message to delete>}`<br/>\n\n\n\n<a name=\"processActivity\"></a>\n### processActivity()\nAccept an incoming webhook request and convert it into a TurnContext which can be processed by the bot's logic.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| req| any | A request object from Restify or Express\n| res| any | A response object from Restify or Express\n| logic|  | A bot logic function in the form `async(context) => { ... }`<br/>\n\n\n\n<a name=\"sendActivities\"></a>\n### sendActivities()\nStandard BotBuilder adapter method to send a message from the bot to the messaging API.\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#sendactivities).\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| context| TurnContext | A TurnContext representing the current incoming message and environment. (Not used)\n| activities|  | An array of outgoing activities to be sent back to the messaging API.<br/>\n\n\n\n<a name=\"updateActivity\"></a>\n### updateActivity()\nStandard BotBuilder adapter method to update a previous message with new content.\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#updateactivity).\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| context| TurnContext | A TurnContext representing the current incoming message and environment. (Not used)\n| activity| Partial&lt;Activity&gt; | The updated activity in the form `{id: <id of activity to update>, text: <updated text>, cards?: [<array of updated hangouts cards>]}`<br/>\n\n\n\n\n<a name=\"HangoutsBotWorker\"></a>\n## HangoutsBotWorker\nThis is a specialized version of [Botkit's core BotWorker class](#BotWorker) that includes additional methods for interacting with Google Hangouts.\nIt includes all functionality from the base class, as well as the extension methods below.\n\nWhen using the HangoutsAdapter with Botkit, all `bot` objects passed to handler functions will include these extensions.\n\n\nTo use this class in your application, first install the package:\n```bash\nnpm install --save botbuilder-adapter-hangouts\n```\n\nThen import this and other classes into your code:\n```javascript\nconst { HangoutsBotWorker } = require('botbuilder-adapter-hangouts');\n```\n\nThis class includes the following methods:\n* [deleteMessage()](#deleteMessage)\n* [replyInThread()](#replyInThread)\n* [replyWithNew()](#replyWithNew)\n* [replyWithUpdate()](#replyWithUpdate)\n* [startConversationInThread()](#startConversationInThread)\n* [updateMessage()](#updateMessage)\n\n\n\n\n## Properties and Accessors\n\n| Name | Type | Description\n|--- |--- |---\n| api | any | Access to the official [Google API client for Hangouts](https://www.npmjs.com/package/googleapis)\n\n## HangoutsBotWorker Class Methods\n<a name=\"deleteMessage\"></a>\n### deleteMessage()\nDelete an existing message.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| update| Partial&lt;BotkitMessage&gt; | An object in the form of `{id: <id of message to delete>}`<br/>\n\n\n\n```javascript\n// send a reply, capture the results\nlet sent = await bot.reply(message,'this is my original reply...');\n\n// delete the sent message using the sent.id field\nawait bot.deleteMessage(sent);\n```\n\n\n<a name=\"replyInThread\"></a>\n### replyInThread()\nReply to an incoming message in a brand new thread.  Works for a single message reply - if multiple replies or replying with a dialog is necessary, use [startConversationInThread](#startconversationinthread).\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| src| any | An incoming message or event object\n| resp| any | A reply message containing text and/or cards<br/>\n\n\n\n```javascript\ncontroller.hears('thread','message', async(bot, message) =>{\n     await bot.replyInThread(message,'This will appear in a new thread.');\n});\n```\n\n<a name=\"replyWithNew\"></a>\n### replyWithNew()\nReply to a card_click event with a new message. [See Google doc for interactive cards &rarr;](https://developers.google.com/hangouts/chat/how-tos/cards-onclick#responding_to_clicks_with_a_new_or_updated_message).\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| src| any | An incoming event object representing a card_clicked event\n| resp| Partial&lt;BotkitMessage&gt; | A reply message containing text and/or cards<br/>\n\n\n\nWhen a user clicks a button contained in a card attachment, a `card_clicked` event will be emitted.\nIn order to reply to the incoming event with a new message (rather than replacing the original card), use this method!\n\n```javascript\ncontroller.on('card_clicked', async(bot, message) => {\n     // check message.action.actionMethodName to see what button was clicked...\n     await bot.replyWithNew(message,'Reply to button click!');\n})\n```\n\n\n<a name=\"replyWithUpdate\"></a>\n### replyWithUpdate()\nReply to a card_click event with an update to the original message. [See Google doc for interactive cards &rarr;](https://developers.google.com/hangouts/chat/how-tos/cards-onclick#responding_to_clicks_with_a_new_or_updated_message).\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| src| any | An incoming event object representing a card_clicked event\n| resp| Partial&lt;BotkitMessage&gt; | A reply message containing text and/or cards<br/>\n\n\n\nWhen a user clicks a button contained in a card attachment, a `card_clicked` event will be emitted.\nIn order to reply to the incoming event by replacing the original message, use this method!\n\n```javascript\ncontroller.on('card_clicked', async(bot, message) => {\n     // check message.action.actionMethodName to see what button was clicked...\n     await bot.replyWithUpdate(message,'Reply to button click!');\n})\n```\n\n\n<a name=\"startConversationInThread\"></a>\n### startConversationInThread()\nSwitch the bot's active context to a new thread.\nUse this to change the location of a bot's responses or calls to beginDialog into a new conversation thread (rather than continuing in the same thread as the originating message)\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| spaceName| string | The name of the main space - usually `message.channel`\n| userId| string | The id of the user conducting the conversation - usually `message.user`\n| threadKey (optional)| string | An optional key definining the thread - if one is not provided, a random one is generated.<br/>\n\n\n\n```javascript\ncontroller.hears('new thread', 'message', async(bot, message) => {\n\n     // change to a new thread\n     await bot.startConversationInThread(message.channel, message.user);\n\n     // begin a dialog in the new thread\n     await bot.beginDialog('foo');\n\n});\n```\n\n\n<a name=\"updateMessage\"></a>\n### updateMessage()\nUpdate an existing message with new content.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| update| Partial&lt;BotkitMessage&gt; | An object in the form `{id: <id of message to update>, text: <new text>, card: <array of card objects>}`<br/>\n\n\n\n```javascript\n// send a reply, capture the results\nlet sent = await bot.reply(message,'this is my original reply...');\n\n// update the sent message using the sent.id field\nawait bot.updateMessage({\n     id: sent.id,\n     text: 'this is an update!',\n})\n```\n\n\n\n\n<a name=\"HangoutsAdapterOptions\"></a>\n## Interface HangoutsAdapterOptions\n\n\n**Fields**\n\n| Name | Type | Description\n|--- |--- |---\n| enable_incomplete | boolean | Allow the adapter to startup without a complete configuration.<br/>This is risky as it may result in a non-functioning or insecure adapter.<br/>This should only be used when getting started.<br/>\n| google_auth_params |  | Parameters passed to the [Google API client library](https://www.npmjs.com/package/googleapis) which is in turn used to send messages.<br/>Define credentials per [the GoogleAuthOptions defined here](https://github.com/googleapis/google-auth-library-nodejs/blob/master/src/auth/googleauth.ts#L54),<br/>OR, specify GOOGLE_APPLICATION_CREDENTIALS in environment [as described in the Google docs](https://cloud.google.com/docs/authentication/getting-started).<br/>\n| token | string | Shared secret token used to validate the origin of incoming webhooks.<br/>Get this from the [Google API console for your bot app](https://console.cloud.google.com/apis/api/chat.googleapis.com/hangouts-chat) - it is found on the Configuration tab under the heading \"Verification Token\".<br/>If defined, the origin of all incoming webhooks will be validated and any non-matching requests will be rejected.<br/>\n"
  },
  {
    "path": "packages/docs/reference/index.md",
    "content": "# Class Index\n\n[&larr; Botkit Core Docs](../core.md)\n\n* [Botkit Core](../reference/core.md)\n    * [Botkit](../reference/core.md#Botkit)\n    * [BotkitBotFrameworkAdapter](../reference/core.md#BotkitBotFrameworkAdapter)\n    * [TeamsBotWorker](../reference/core.md#TeamsBotWorker)\n    * [BotWorker](../reference/core.md#BotWorker)\n    * [BotkitConversation](../reference/core.md#BotkitConversation)\n    * [BotkitDialogWrapper](../reference/core.md#BotkitDialogWrapper)\n    * [BotkitTestClient](../reference/core.md#BotkitTestClient)\n    * [TeamsInvokeMiddleware](../reference/core.md#TeamsInvokeMiddleware)\n* [Botkit for the Web](../reference/web.md)\n    * [WebAdapter](../reference/web.md#WebAdapter)\n* [Botkit for Webex Teams](../reference/webex.md)\n    * [WebexAdapter](../reference/webex.md#WebexAdapter)\n    * [WebexBotWorker](../reference/webex.md#WebexBotWorker)\n* [Botkit for Slack](../reference/slack.md)\n    * [SlackAdapter](../reference/slack.md#SlackAdapter)\n    * [SlackBotWorker](../reference/slack.md#SlackBotWorker)\n    * [SlackDialog](../reference/slack.md#SlackDialog)\n    * [SlackEventMiddleware](../reference/slack.md#SlackEventMiddleware)\n    * [SlackMessageTypeMiddleware](../reference/slack.md#SlackMessageTypeMiddleware)\n* [Botkit for Hangouts](../reference/hangouts.md)\n    * [HangoutsAdapter](../reference/hangouts.md#HangoutsAdapter)\n    * [HangoutsBotWorker](../reference/hangouts.md#HangoutsBotWorker)\n* [Botkit for Twilio SMS](../reference/twilio-sms.md)\n    * [TwilioAdapter](../reference/twilio-sms.md#TwilioAdapter)\n    * [TwilioBotWorker](../reference/twilio-sms.md#TwilioBotWorker)\n* [Botkit for Facebook](../reference/facebook.md)\n    * [FacebookAdapter](../reference/facebook.md#FacebookAdapter)\n    * [FacebookBotWorker](../reference/facebook.md#FacebookBotWorker)\n    * [FacebookAPI](../reference/facebook.md#FacebookAPI)\n    * [FacebookEventTypeMiddleware](../reference/facebook.md#FacebookEventTypeMiddleware)\n* [Botkit CMS Plugin](../reference/cms.md)\n    * [BotkitCMSHelper](../reference/cms.md#BotkitCMSHelper)\n"
  },
  {
    "path": "packages/docs/reference/slack.md",
    "content": "# Botkit for Slack Class Reference\n\n[&larr; Botkit Documentation](../core.md) [&larr; Class Index](index.md) \n\nThis is a class reference for all the methods exposed by the [botbuilder-adapter-slack](https://github.com/howdyai/botkit/tree/master/packages/botbuilder-adapter-slack) package.\n\n## Classes\n\n\n* <a href=\"#SlackAdapter\" aria-current=\"page\">SlackAdapter</a>\n* <a href=\"#SlackBotWorker\" aria-current=\"page\">SlackBotWorker</a>\n* <a href=\"#SlackDialog\" aria-current=\"page\">SlackDialog</a>\n* <a href=\"#SlackEventMiddleware\" aria-current=\"page\">SlackEventMiddleware</a>\n* <a href=\"#SlackMessageTypeMiddleware\" aria-current=\"page\">SlackMessageTypeMiddleware</a>\n\n## Interfaces\n\n* <a href=\"#SlackAdapterOptions\" aria-current=\"page\">SlackAdapterOptions</a>\n\n---\n\n<a name=\"SlackAdapter\"></a>\n## SlackAdapter\nConnect [Botkit](https://www.npmjs.com/package/botkit) or [BotBuilder](https://www.npmjs.com/package/botbuilder) to Slack.\n\nTo use this class in your application, first install the package:\n```bash\nnpm install --save botbuilder-adapter-slack\n```\n\nThen import this and other classes into your code:\n```javascript\nconst { SlackAdapter } = require('botbuilder-adapter-slack');\n```\n\nThis class includes the following methods:\n* [activityToSlack()](#activityToSlack)\n* [continueConversation()](#continueConversation)\n* [deleteActivity()](#deleteActivity)\n* [getAPI()](#getAPI)\n* [getBotUserByTeam()](#getBotUserByTeam)\n* [getInstallLink()](#getInstallLink)\n* [processActivity()](#processActivity)\n* [sendActivities()](#sendActivities)\n* [updateActivity()](#updateActivity)\n* [validateOauthCode()](#validateOauthCode)\n\n\n\n### Create a new SlackAdapter()\n**Parameters**\n\n| Argument | Type | Description\n|--- |--- |---\n| options | [SlackAdapterOptions](#SlackAdapterOptions) | An object containing API credentials, a webhook verification token and other options<br/>\n\nCreate a Slack adapter.\n\nThe SlackAdapter can be used in 2 modes:\n     * As an \"[internal integration](https://api.slack.com/internal-integrations) connected to a single Slack workspace\n     * As a \"[Slack app](https://api.slack.com/slack-apps) that uses oauth to connect to multiple workspaces and can be submitted to the Slack app.\n\n[Read here for more information about all the ways to configure the SlackAdapter &rarr;](../../botbuilder-adapter-slack/readme.md).\n\nUse with Botkit:\n```javascript\nconst adapter = new SlackAdapter({\n     clientSigningSecret: process.env.CLIENT_SIGNING_SECRET,\n     botToken: process.env.BOT_TOKEN\n});\nconst controller = new Botkit({\n     adapter: adapter,\n     // ... other configuration options\n});\n```\n\nUse with BotBuilder:\n```javascript\nconst adapter = new SlackAdapter({\n     clientSigningSecret: process.env.CLIENT_SIGNING_SECRET,\n     botToken: process.env.BOT_TOKEN\n});\n// set up restify...\nconst server = restify.createServer();\nserver.use(restify.plugins.bodyParser());\nserver.post('/api/messages', (req, res) => {\n     adapter.processActivity(req, res, async(context) => {\n         // do your bot logic here!\n     });\n});\n```\n\nUse in \"Slack app\" multi-team mode:\n```javascript\nconst adapter = new SlackAdapter({\n    clientSigningSecret: process.env.CLIENT_SIGNING_SECRET,\n    clientId: process.env.CLIENT_ID, // oauth client id\n    clientSecret: process.env.CLIENT_SECRET, // oauth client secret\n    scopes: ['bot'], // oauth scopes requested\n    oauthVersion: 'v1',\n    redirectUri: process.env.REDIRECT_URI, // url to redirect post login defaults to `https://<mydomain>/install/auth`\n    getTokenForTeam: async(team_id) => Promise<string>, // function that returns a token based on team id\n    getBotUserByTeam: async(team_id) => Promise<string>, // function that returns a bot's user id based on team id\n});\n```\n\n\n\n\n## SlackAdapter Class Methods\n<a name=\"activityToSlack\"></a>\n### activityToSlack()\nFormats a BotBuilder activity into an outgoing Slack message.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| activity| Partial&lt;Activity&gt; | A BotBuilder Activity object\n\n\n**Returns**\n\na Slack message object with {text, attachments, channel, thread_ts} as well as any fields found in activity.channelData\n\n\n\n\n<a name=\"continueConversation\"></a>\n### continueConversation()\nStandard BotBuilder adapter method for continuing an existing conversation based on a conversation reference.\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#continueconversation)\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| reference| Partial&lt;ConversationReference&gt; | A conversation reference to be applied to future messages.\n| logic|  | A bot logic function that will perform continuing action in the form `async(context) => { ... }`<br/>\n\n\n\n<a name=\"deleteActivity\"></a>\n### deleteActivity()\nStandard BotBuilder adapter method to delete a previous message.\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#deleteactivity).\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| context| TurnContext | A TurnContext representing the current incoming message and environment.\n| reference| Partial&lt;ConversationReference&gt; | An object in the form `{activityId: <id of message to delete>, conversation: { id: <id of slack channel>}}`<br/>\n\n\n\n<a name=\"getAPI\"></a>\n### getAPI()\nGet a Slack API client with the correct credentials based on the team identified in the incoming activity.\nThis is used by many internal functions to get access to the Slack API, and is exposed as `bot.api` on any bot worker instances.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| activity| Partial&lt;Activity&gt; | An incoming message activity<br/>\n\n\n\n<a name=\"getBotUserByTeam\"></a>\n### getBotUserByTeam()\nGet the bot user id associated with the team on which an incoming activity originated. This is used internally by the SlackMessageTypeMiddleware to identify direct_mention and mention events.\nIn single-team mode, this will pull the information from the Slack API at launch.\nIn multi-team mode, this will use the `getBotUserByTeam` method passed to the constructor to pull the information from a developer-defined source.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| activity| Partial&lt;Activity&gt; | An incoming message activity<br/>\n\n\n\n<a name=\"getInstallLink\"></a>\n### getInstallLink()\nGet the oauth link for this bot, based on the clientId and scopes passed in to the constructor.\n\n**Returns**\n\nA url pointing to the first step in Slack&#x27;s oauth flow.\n\n\n\n\nAn example using Botkit's internal webserver to configure the /install route:\n\n```javascript\ncontroller.webserver.get('/install', (req, res) => {\n res.redirect(controller.adapter.getInstallLink());\n});\n```\n\n\n<a name=\"processActivity\"></a>\n### processActivity()\nAccept an incoming webhook request and convert it into a TurnContext which can be processed by the bot's logic.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| req| any | A request object from Restify or Express\n| res| any | A response object from Restify or Express\n| logic|  | A bot logic function in the form `async(context) => { ... }`<br/>\n\n\n\n<a name=\"sendActivities\"></a>\n### sendActivities()\nStandard BotBuilder adapter method to send a message from the bot to the messaging API.\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#sendactivities).\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| context| TurnContext | A TurnContext representing the current incoming message and environment.\n| activities|  | An array of outgoing activities to be sent back to the messaging API.<br/>\n\n\n\n<a name=\"updateActivity\"></a>\n### updateActivity()\nStandard BotBuilder adapter method to update a previous message with new content.\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#updateactivity).\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| context| TurnContext | A TurnContext representing the current incoming message and environment.\n| activity| Partial&lt;Activity&gt; | The updated activity in the form `{id: <id of activity to update>, ...}`<br/>\n\n\n\n<a name=\"validateOauthCode\"></a>\n### validateOauthCode()\nValidates an oauth v2 code sent by Slack during the install process.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| code| string | the value found in `req.query.code` as part of Slack's response to the oauth flow.<br/>\n\n\n\nAn example using Botkit's internal webserver to configure the /install/auth route:\n\n```javascript\ncontroller.webserver.get('/install/auth', async (req, res) => {\n     try {\n         const results = await controller.adapter.validateOauthCode(req.query.code);\n         // make sure to capture the token and bot user id by team id...\n         const team_id = results.team.id;\n         const token = results.access_token;\n         const bot_user = results.bot_user_id;\n         // store these values in a way they'll be retrievable with getBotUserByTeam and getTokenForTeam\n     } catch (err) {\n          console.error('OAUTH ERROR:', err);\n          res.status(401);\n          res.send(err.message);\n     }\n});\n```\n\n\n<a name=\"SlackBotWorker\"></a>\n## SlackBotWorker\nThis is a specialized version of [Botkit's core BotWorker class](core.md#BotWorker) that includes additional methods for interacting with Slack.\nIt includes all functionality from the base class, as well as the extension methods below.\n\nWhen using the SlackAdapter with Botkit, all `bot` objects passed to handler functions will include these extensions.\n\n\nTo use this class in your application, first install the package:\n```bash\nnpm install --save botbuilder-adapter-slack\n```\n\nThen import this and other classes into your code:\n```javascript\nconst { SlackBotWorker } = require('botbuilder-adapter-slack');\n```\n\nThis class includes the following methods:\n* [deleteMessage()](#deleteMessage)\n* [dialogError()](#dialogError)\n* [replyEphemeral()](#replyEphemeral)\n* [replyInThread()](#replyInThread)\n* [replyInteractive()](#replyInteractive)\n* [replyPrivate()](#replyPrivate)\n* [replyPublic()](#replyPublic)\n* [replyWithDialog()](#replyWithDialog)\n* [startConversationInChannel()](#startConversationInChannel)\n* [startConversationInThread()](#startConversationInThread)\n* [startPrivateConversation()](#startPrivateConversation)\n* [updateMessage()](#updateMessage)\n\n\n\n### Create a new SlackBotWorker()\n**Parameters**\n\n| Argument | Type | Description\n|--- |--- |---\n| botkit | Botkit | The Botkit controller object responsible for spawning this bot worker\n| config | any | Normally, a DialogContext object.  Can also be the id of a team.<br/>\n\nReserved for use internally by Botkit's `controller.spawn()`, this class is used to create a BotWorker instance that can send messages, replies, and make other API calls.\n\nIt is possible to spawn a bot instance by passing in the Slack workspace ID of a team that has installed the app.\nUse this in concert with [startPrivateConversation()](#startPrivateConversation) and [changeContext()](core.md#changecontext) to start conversations\nor send proactive alerts to users on a schedule or in response to external events.\n\n\n```javascript\n// spawn a bot for a given team.\nlet bot = await controller.spawn('T0123456');\n\n// start a 1:1 with a specific user\nawait bot.startPrivateConversation('U0123456');\n\n// send a message\nawait bot.say('Hi user');\n```\n\n\n\n## Properties and Accessors\n\n| Name | Type | Description\n|--- |--- |---\n| api | WebClient | A copy of hte Slack WebClient giving, giving access to all of Slack's APIs via `let res = await bot.api.object.method(params);`\n\n## SlackBotWorker Class Methods\n<a name=\"deleteMessage\"></a>\n### deleteMessage()\nDelete an existing message.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| update| Partial&lt;BotkitMessage&gt; | An object in the form of `{id: <id of message to delete>, conversation: { id: <channel of message> }}`<br/>\n\n\n\n```javascript\n// send a reply, capture the results\nlet sent = await bot.reply(message,'this is my original reply...');\n\n// delete the sent message using the sent.id field\nawait bot.deleteMessage(sent);\n```\n\n\n<a name=\"dialogError\"></a>\n### dialogError()\nReturn 1 or more error to a `dialog_submission` event that will be displayed as form validation errors.\nEach error must be mapped to the name of an input in the dialog.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| errors|  | 1 or more objects in form {name: string, error: string}<br/>\n\n\n\n<a name=\"replyEphemeral\"></a>\n### replyEphemeral()\nLike bot.reply, but sent as an \"ephemeral\" message meaning only the recipient can see it.\nUses [chat.postEphemeral](https://api.slack.com/methods/chat.postEphemeral)\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| src| any | an incoming message object\n| resp| any | an outgoing message object (or part of one or just reply text)<br/>\n\n\n\n<a name=\"replyInThread\"></a>\n### replyInThread()\nLike bot.reply, but as a threaded response to the incoming message rather than a new message in the main channel.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| src| any | an incoming message object\n| resp| any | an outgoing message object (or part of one or just reply text)<br/>\n\n\n\n<a name=\"replyInteractive\"></a>\n### replyInteractive()\nLike bot.reply, but used to respond to an `interactive_message` event and cause the original message to be replaced with a new one.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| src| any | an incoming message object of type `interactive_message`\n| resp| any | a new or modified message that will replace the original one<br/>\n\n\n\n<a name=\"replyPrivate\"></a>\n### replyPrivate()\nLike bot.reply, but used to send an immediate private reply to a /slash command.\nThe message in `resp` will be displayed only to the person who executed the slash command.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| src| any | an incoming message object of type `slash_command`\n| resp| any | an outgoing message object (or part of one or just reply text)<br/>\n\n\n\n<a name=\"replyPublic\"></a>\n### replyPublic()\nLike bot.reply, but used to send an immediate public reply to a /slash command.\nThe message in `resp` will be displayed to everyone in the channel.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| src| any | an incoming message object of type `slash_command`\n| resp| any | an outgoing message object (or part of one or just reply text)<br/>\n\n\n\n<a name=\"replyWithDialog\"></a>\n### replyWithDialog()\nReply to a button click with a request to open a dialog.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| src| any | An incoming `interactive_callback` event containing a `trigger_id` field\n| dialog_obj| Dialog | A dialog, as created using [SlackDialog](#SlackDialog) or [authored to this spec](https://api.slack.com/dialogs).<br/>\n\n\n\n<a name=\"startConversationInChannel\"></a>\n### startConversationInChannel()\nSwitch a bot's context into a different channel.\nAfter calling this method, messages sent with `bot.say` and any dialogs started with `bot.beginDialog` will occur in this new context.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| channelId| string | A Slack channel id, like one found in `message.channel`\n| userId| string | A Slack user id, like one found in `message.user` or in a `<@mention>`<br/>\n\n\n\n```javascript\ncontroller.hears('dm me', 'message', async(bot, message) => {\n\n     // switch to the channel specified in SLACK_CHANNEL_ID\n     // if just using bot.say and not starting a dialog, can use a fake value for user id.\n     await bot.startConversationInChannel(SLACK_CHANNEL_ID, message.user);\n\n     // say hello\n     await bot.say('Shall we discuss this matter over here?');\n     // ... continue...\n     await bot.beginDialog(ANOTHER_DIALOG);\n\n});\n```\n\n<a name=\"startConversationInThread\"></a>\n### startConversationInThread()\nSwitch a bot's context into a specific sub-thread within a channel.\nAfter calling this method, messages sent with `bot.say` and any dialogs started with `bot.beginDialog` will occur in this new context.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| channelId| string | A Slack channel id, like one found in `message.channel`\n| userId| string | A Slack user id, like one found in `message.user` or in a `<@mention>`\n| thread_ts| string | A thread_ts value found in the `message.thread_ts` or `message.ts` field.<br/>\n\n\n\n```javascript\ncontroller.hears('in a thread', 'message', async(bot, message) => {\n\n     // branch from the main channel into a side thread associated with this message\n     await bot.startConversationInThread(message.channel, message.user, message.ts);\n\n     // say hello\n     await bot.say(`Let's handle this offline...`);\n     // ... continue...\n     await bot.beginDialog(OFFLINE_DIALOG);\n\n});\n```\n\n<a name=\"startPrivateConversation\"></a>\n### startPrivateConversation()\nSwitch a bot's context to a 1:1 private message channel with a specific user.\nAfter calling this method, messages sent with `bot.say` and any dialogs started with `bot.beginDialog` will occur in this new context.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| userId| string | A Slack user id, like one found in `message.user` or in a `<@mention>`<br/>\n\n\n\n```javascript\ncontroller.hears('dm me', 'message', async(bot, message) => {\n\n     // switch to a 1:1 conversation in a DM\n     await bot.startPrivateConversation(message.user);\n\n     // say hello\n     await bot.say('We are in private now...');\n     await bot.beginDialog(MY_PRIVATE_DIALOG);\n\n});\n```\n\nAlso useful when sending pro-active messages such as those sent on a schedule or in response to external events:\n```javascript\n// Spawn a worker with a Slack team id.\nlet bot = await controller.spawn(SLACK_TEAM_ID);\n\n// Set the context for the bot's next action...\nawait bot.startPrivateConversation(SLACK_ADMIN_USER);\n\n// Begin a dialog in the 1:1 context\nawait bot.beginDialog(ALERT_DIALOG);\n```\n\n\n<a name=\"updateMessage\"></a>\n### updateMessage()\nUpdate an existing message with new content.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| update| Partial&lt;BotkitMessage&gt; | An object in the form `{id: <id of message to update>, conversation: { id: <channel> }, text: <new text>, card: <array of card objects>}`<br/>\n\n\n\n```javascript\n// send a reply, capture the results\nlet sent = await bot.reply(message,'this is my original reply...');\n\n// update the sent message using the sent.id field\nawait bot.updateMessage({\n     text: 'this is an update!',\n     ...sent\n})\n```\n\n\n\n<a name=\"SlackDialog\"></a>\n## SlackDialog\nCreate a Slack Dialog object for use with [replyWithDialog()](#replyWithDialog).\n\n```javascript\nlet dialog = new SlackDialog('My Dialog', 'callback_123', 'Save');\ndialog.addText('Your full name', 'name').addEmail('Your email', 'email');\ndialog.notifyOnCancel(true);\nbot.replyWithDialog(message, dialog.asObject());\n```\n\n\n\nTo use this class in your application, first install the package:\n```bash\nnpm install --save botbuilder-adapter-slack\n```\n\nThen import this and other classes into your code:\n```javascript\nconst { SlackDialog } = require('botbuilder-adapter-slack');\n```\n\nThis class includes the following methods:\n* [addEmail()](#addEmail)\n* [addNumber()](#addNumber)\n* [addSelect()](#addSelect)\n* [addTel()](#addTel)\n* [addText()](#addText)\n* [addTextarea()](#addTextarea)\n* [addUrl()](#addUrl)\n* [asObject()](#asObject)\n* [asString()](#asString)\n* [callback_id()](#callback_id)\n* [notifyOnCancel()](#notifyOnCancel)\n* [state()](#state)\n* [submit_label()](#submit_label)\n* [title()](#title)\n\n\n\n### Create a new SlackDialog()\n**Parameters**\n\n| Argument | Type | Description\n|--- |--- |---\n| title | string | Title of dialog\n| callback_id | string | Callback id of dialog\n| submit_label | string | Label for the submit button\n| elements | any | An array of dialog elements<br/>\n\nCreate a new dialog object\n\n\n\n## SlackDialog Class Methods\n<a name=\"addEmail\"></a>\n### addEmail()\nAdd an email input to the dialog\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| label| string | \n| name| string | \n| value| string | \n| options (optional)| any | <br/>\n\n\n\n<a name=\"addNumber\"></a>\n### addNumber()\nAdd a number input to the dialog\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| label| string | \n| name| string | \n| value| string | \n| options (optional)| any | <br/>\n\n\n\n<a name=\"addSelect\"></a>\n### addSelect()\nAdd a dropdown select input to the dialog\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| label| string | \n| name| string | \n| value|  | \n| option_list|  | \n| options (optional)| any | <br/>\n\n\n\n<a name=\"addTel\"></a>\n### addTel()\nAdd a telephone number input to the dialog\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| label| string | \n| name| string | \n| value| string | \n| options (optional)| any | <br/>\n\n\n\n<a name=\"addText\"></a>\n### addText()\nAdd a text input to the dialog\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| label|  | \n| name| string | \n| value| string | \n| options|  | \n| subtype (optional)| string | <br/>\n\n\n\n<a name=\"addTextarea\"></a>\n### addTextarea()\nAdd a text area input to the dialog\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| label| string | \n| name| string | \n| value| string | \n| options| any | \n| subtype| string | <br/>\n\n\n\n<a name=\"addUrl\"></a>\n### addUrl()\nAdd a URL input to the dialog\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| label| string | \n| name| string | \n| value| string | \n| options (optional)| any | <br/>\n\n\n\n<a name=\"asObject\"></a>\n### asObject()\nGet the dialog object for use with bot.replyWithDialog()\n\n\n<a name=\"asString\"></a>\n### asString()\nGet the dialog object as a JSON encoded string.\n\n\n<a name=\"callback_id\"></a>\n### callback_id()\nSet the dialog's callback_id\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| v| string | Value for the callback_id<br/>\n\n\n\n<a name=\"notifyOnCancel\"></a>\n### notifyOnCancel()\nSet true to have Slack notify you with a `dialog_cancellation` event if a user cancels the dialog without submitting\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| set| boolean | True or False<br/>\n\n\n\n<a name=\"state\"></a>\n### state()\nSet the dialog's state field\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| v| any | value for state<br/>\n\n\n\n<a name=\"submit_label\"></a>\n### submit_label()\nSet the button text for the submit button on the dialog\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| v| string | Value for the button label<br/>\n\n\n\n<a name=\"title\"></a>\n### title()\nSet the title of the dialog\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| v| string | Value for title<br/>\n\n\n\n\n<a name=\"SlackEventMiddleware\"></a>\n## SlackEventMiddleware\nA middleware for Botkit developers using the BotBuilder SlackAdapter class.\nThis middleware causes Botkit to emit message events by their `type` or `subtype` field rather than their default BotBuilder Activity type (limited to message or event).\nThis keeps the new Botkit behavior consistent withprevious versions, and provides helpful filtering on the many event types that Slack sends.\nTo use this, bind it to the adapter before creating the Botkit controller:\n```javascript\nconst adapter = new SlackAdapter(options);\nadapter.use(new SlackEventMiddleware());\nconst controller = new Botkit({\n     adapter: adapter,\n     // ...\n});\n\n// can bind directly to channel_join (which starts as a message with type message and subtype channel_join)\ncontroller.on('channel_join', async(bot, message) => {\n // send a welcome\n});\n```\n\n\nTo use this class in your application, first install the package:\n```bash\nnpm install --save botbuilder-adapter-slack\n```\n\nThen import this and other classes into your code:\n```javascript\nconst { SlackEventMiddleware } = require('botbuilder-adapter-slack');\n```\n\nThis class includes the following methods:\n* [onTurn()](#onTurn)\n\n\n\n\n\n## SlackEventMiddleware Class Methods\n<a name=\"onTurn\"></a>\n### onTurn()\nNot for direct use - implements the MiddlewareSet's required onTurn function used to process the event\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| context| TurnContext | \n| next|  | <br/>\n\n\n\n\n<a name=\"SlackMessageTypeMiddleware\"></a>\n## SlackMessageTypeMiddleware\nA middleware for Botkit developers using the BotBuilder SlackAdapter class.\nThis middleware causes Botkit to emit more specialized events for the different types of message that Slack might send.\nResponsible for classifying messages:\n\n     * `direct_message` events are messages received through 1:1 direct messages with the bot\n     * `direct_mention` events are messages that start with a mention of the bot, i.e \"@mybot hello there\"\n     * `mention` events are messages that include a mention of the bot, but not at the start, i.e \"hello there @mybot\"\n\nIn addition, messages from bots and changing them to `bot_message` events. All other types of message encountered remain `message` events.\n\nTo use this, bind it to the adapter before creating the Botkit controller:\n```javascript\nconst adapter = new SlackAdapter(options);\nadapter.use(new SlackMessageTypeMiddleware());\nconst controller = new Botkit({\n     adapter: adapter,\n     // ...\n});\n```\n\n\nTo use this class in your application, first install the package:\n```bash\nnpm install --save botbuilder-adapter-slack\n```\n\nThen import this and other classes into your code:\n```javascript\nconst { SlackMessageTypeMiddleware } = require('botbuilder-adapter-slack');\n```\n\nThis class includes the following methods:\n* [onTurn()](#onTurn)\n\n\n\n\n\n## SlackMessageTypeMiddleware Class Methods\n<a name=\"onTurn\"></a>\n### onTurn()\nNot for direct use - implements the MiddlewareSet's required onTurn function used to process the event\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| context| TurnContext | \n| next|  | <br/>\n\n\n\n\n\n<a name=\"SlackAdapterOptions\"></a>\n## Interface SlackAdapterOptions\nThis interface defines the options that can be passed into the SlackAdapter constructor function.\n\n**Fields**\n\n| Name | Type | Description\n|--- |--- |---\n| botToken | string | A token (provided by Slack) for a bot to work on a single workspace<br/>\n| clientId | string | The oauth client id provided by Slack for multi-team apps<br/>\n| clientSecret | string | The oauth client secret provided by Slack for multi-team apps<br/>\n| clientSigningSecret | string | A token used to validate that incoming webhooks originated with Slack.<br/>\n| enable_incomplete | boolean | Allow the adapter to startup without a complete configuration.<br/>This is risky as it may result in a non-functioning or insecure adapter.<br/>This should only be used when getting started.<br/>\n| getBotUserByTeam |  | A method that receives a Slack team id and returns the bot user id associated with that team. Required for multi-team apps.<br/>\n| getTokenForTeam |  | A method that receives a Slack team id and returns the bot token associated with that team. Required for multi-team apps.<br/>\n| oauthVersion | string | Which version of Slack's oauth protocol to use, v1 or v2. Defaults to v1.<br/>\n| redirectUri | string | The URL users will be redirected to after an oauth flow. In most cases, should be `https://<mydomain.com>/install/auth`<br/>\n| scopes |  | A array of scope names that are being requested during the oauth process. Must match the scopes defined at api.slack.com<br/>\n| verificationToken | string | Legacy method for validating the origin of incoming webhooks. Prefer `clientSigningSecret` instead.<br/>\n"
  },
  {
    "path": "packages/docs/reference/twilio-sms.md",
    "content": "# Botkit for Twilio SMS Class Reference\n\n[&larr; Botkit Documentation](../core.md) [&larr; Class Index](index.md) \n\nThis is a class reference for all the methods exposed by the [botbuilder-adapter-twilio-sms](https://github.com/howdyai/botkit/tree/master/packages/botbuilder-adapter-twilio-sms) package.\n\n## Classes\n\n\n* <a href=\"#TwilioAdapter\" aria-current=\"page\">TwilioAdapter</a>\n* <a href=\"#TwilioBotWorker\" aria-current=\"page\">TwilioBotWorker</a>\n\n## Interfaces\n\n* <a href=\"#TwilioAdapterOptions\" aria-current=\"page\">TwilioAdapterOptions</a>\n\n---\n\n<a name=\"TwilioAdapter\"></a>\n## TwilioAdapter\nConnect [Botkit](https://www.npmjs.com/package/botkit) or [BotBuilder](https://www.npmjs.com/package/botbuilder) to Twilio's SMS service.\n\nTo use this class in your application, first install the package:\n```bash\nnpm install --save botbuilder-adapter-twilio-sms\n```\n\nThen import this and other classes into your code:\n```javascript\nconst { TwilioAdapter } = require('botbuilder-adapter-twilio-sms');\n```\n\nThis class includes the following methods:\n* [continueConversation()](#continueConversation)\n* [processActivity()](#processActivity)\n* [sendActivities()](#sendActivities)\n\n\n\n### Create a new TwilioAdapter()\n**Parameters**\n\n| Argument | Type | Description\n|--- |--- |---\n| options | [TwilioAdapterOptions](#TwilioAdapterOptions) | An object containing API credentials, a webhook verification token and other options<br/>\n\nCreate an adapter to handle incoming messages from Twilio's SMS service and translate them into a standard format for processing by your bot.\n\nUse with Botkit:\n```javascript\nconst adapter = new TwilioAdapter({\n     twilio_number: process.env.TWILIO_NUMBER,\n     account_sid: process.env.TWILIO_ACCOUNT_SID,\n     auth_token: process.env.TWILIO_AUTH_TOKEN,\n     validation_url: process.env.TWILIO_VALIDATION_URL\n});\nconst controller = new Botkit({\n     adapter: adapter,\n     // ... other configuration options\n});\n```\n\nUse with BotBuilder:\n```javascript\nconst adapter = new TwilioAdapter({\n     twilio_number: process.env.TWILIO_NUMBER,\n     account_sid: process.env.TWILIO_ACCOUNT_SID,\n     auth_token: process.env.TWILIO_AUTH_TOKEN,\n     validation_url: process.env.TWILIO_VALIDATION_URL\n});\n// set up restify...\nconst server = restify.createServer();\nserver.use(restify.plugins.bodyParser());\nserver.post('/api/messages', (req, res) => {\n     adapter.processActivity(req, res, async(context) => {\n         // do your bot logic here!\n     });\n});\n```\n\n\n\n\n## TwilioAdapter Class Methods\n<a name=\"continueConversation\"></a>\n### continueConversation()\nStandard BotBuilder adapter method for continuing an existing conversation based on a conversation reference.\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#continueconversation)\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| reference| Partial&lt;ConversationReference&gt; | A conversation reference to be applied to future messages.\n| logic|  | A bot logic function that will perform continuing action in the form `async(context) => { ... }`<br/>\n\n\n\n<a name=\"processActivity\"></a>\n### processActivity()\nAccept an incoming webhook request and convert it into a TurnContext which can be processed by the bot's logic.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| req| any | A request object from Restify or Express\n| res| any | A response object from Restify or Express\n| logic|  | A bot logic function in the form `async(context) => { ... }`<br/>\n\n\n\n<a name=\"sendActivities\"></a>\n### sendActivities()\nStandard BotBuilder adapter method to send a message from the bot to the messaging API.\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#sendactivities).\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| context| TurnContext | A TurnContext representing the current incoming message and environment. (Not used)\n| activities|  | An array of outgoing activities to be sent back to the messaging API.<br/>\n\n\n\n\n<a name=\"TwilioBotWorker\"></a>\n## TwilioBotWorker\nThis is a specialized version of [Botkit's core BotWorker class](core.md#BotWorker) that includes additional methods for interacting with Twilio SMS.\nIt includes all functionality from the base class, as well as the extension methods below.\n\nWhen using the TwilioAdapter with Botkit, all `bot` objects passed to handler functions will include these extensions.\n\n\nTo use this class in your application, first install the package:\n```bash\nnpm install --save botbuilder-adapter-twilio-sms\n```\n\nThen import this and other classes into your code:\n```javascript\nconst { TwilioBotWorker } = require('botbuilder-adapter-twilio-sms');\n```\n\nThis class includes the following methods:\n* [startConversationWithUser()](#startConversationWithUser)\n\n\n\n\n## Properties and Accessors\n\n| Name | Type | Description\n|--- |--- |---\n| api | Twilio.Twilio | A copy of the Twilio API client.\n\n## TwilioBotWorker Class Methods\n<a name=\"startConversationWithUser\"></a>\n### startConversationWithUser()\nStart a conversation with a given user identified by their phone number. Useful for sending pro-active messages:\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| userId| string | A phone number in the form +1XXXYYYZZZZ<br/>\n\n\n\n```javascript\nlet bot = await controller.spawn();\nawait bot.startConversationWithUser(MY_PHONE_NUMBER);\nawait bot.send('An important update!');\n```\n\n\n\n\n<a name=\"TwilioAdapterOptions\"></a>\n## Interface TwilioAdapterOptions\nParameters passed to the TwilioAdapter constructor.\n\n**Fields**\n\n| Name | Type | Description\n|--- |--- |---\n| account_sid | string | The account SID from the twilio account<br/>\n| auth_token | string | An api auth token associated with the twilio account<br/>\n| enable_incomplete | boolean | Allow the adapter to startup without a complete configuration.<br/>This is risky as it may result in a non-functioning or insecure adapter.<br/>This should only be used when getting started.<br/>\n| twilio_number | string | The phone number associated with this Twilio app, in the format 1XXXYYYZZZZ<br/>\n| validation_url | string | An optional url to override the automatically generated url signature used to validate incoming requests -- [See Twilio docs about securing your endpoint.](https://www.twilio.com/docs/usage/security#validating-requests)<br/>\n"
  },
  {
    "path": "packages/docs/reference/web.md",
    "content": "# Botkit for the Web Class Reference\n\n[&larr; Botkit Documentation](../core.md) [&larr; Class Index](index.md) \n\nThis is a class reference for all the methods exposed by the [botbuilder-adapter-web](https://github.com/howdyai/botkit/tree/master/packages/botbuilder-adapter-web) package.\n\n## Classes\n\n\n* <a href=\"#WebAdapter\" aria-current=\"page\">WebAdapter</a>\n\n\n---\n\n<a name=\"WebAdapter\"></a>\n## WebAdapter\nConnect [Botkit](https://www.npmjs.com/package/botkit) or [BotBuilder](https://www.npmjs.com/package/botbuilder) to the Web.\nIt offers both websocket and webhook capabilities.\nTo use this adapter, you will need a compatible chat client - generate one using the [Botkit yeoman generator](https://npmjs.com/package/generator-botkit),\nor use [the one included in the project repo here.](https://github.com/howdyai/botkit/tree/master/packages/botbuilder-adapter-web/client)\n\nTo use this class in your application, first install the package:\n```bash\nnpm install --save botbuilder-adapter-web\n```\n\nThen import this and other classes into your code:\n```javascript\nconst { WebAdapter } = require('botbuilder-adapter-web');\n```\n\nThis class includes the following methods:\n* [continueConversation()](#continueConversation)\n* [createSocketServer()](#createSocketServer)\n* [getConnection()](#getConnection)\n* [init()](#init)\n* [isConnected()](#isConnected)\n* [processActivity()](#processActivity)\n* [sendActivities()](#sendActivities)\n\n\n\n### Create a new WebAdapter()\n**Parameters**\n\n| Argument | Type | Description\n|--- |--- |---\n| socketServerOptions |  | an optional object containing parameters to send to a call to [WebSocket.server](https://github.com/websockets/ws/blob/master/doc/ws.md#new-websocketserveroptions-callback).<br/>\n\nCreate an adapter to handle incoming messages from a websocket and/or webhook and translate them into a standard format for processing by your bot.\n\nTo use with Botkit:\n```javascript\nconst adapter = new WebAdapter();\nconst controller = new Botkit({\n     adapter: adapter,\n     // other options\n});\n```\n\nTo use with BotBuilder:\n```javascript\nconst adapter = new WebAdapter();\nconst server = restify.createServer();\nserver.use(restify.plugins.bodyParser());\n// instead of binding processActivity to the incoming request, pass in turn handler logic to createSocketServer\nlet options = {}; // socket server configuration options\nadapter.createSocketServer(server, options, async(context) => {\n // handle turn here\n});\n```\n\n\n\n## Properties and Accessors\n\n| Name | Type | Description\n|--- |--- |---\n| wss | any | The websocket server.\n\n## WebAdapter Class Methods\n<a name=\"continueConversation\"></a>\n### continueConversation()\nStandard BotBuilder adapter method for continuing an existing conversation based on a conversation reference.\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#continueconversation)\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| reference| Partial&lt;ConversationReference&gt; | A conversation reference to be applied to future messages.\n| logic|  | A bot logic function that will perform continuing action in the form `async(context) => { ... }`<br/>\n\n\n\n<a name=\"createSocketServer\"></a>\n### createSocketServer()\nBind a websocket listener to an existing webserver object.\nNote: Create the server using Node's http.createServer\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| server| any | an http server\n| socketOptions| any | additional options passed when creating the websocket server with [WebSocket.server](https://github.com/websockets/ws/blob/master/doc/ws.md#new-websocketserveroptions-callback)\n| logic| any | a turn handler function in the form `async(context)=>{ ... }` that will handle the bot's logic.<br/>\n\n\n\n<a name=\"getConnection\"></a>\n### getConnection()\nReturns websocket connection of given user\nExample: `if (message.action === 'disconnect') bot.controller.adapter.getConnection(message.user).terminate()`\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| user| string | <br/>\n\n\n\n<a name=\"init\"></a>\n### init()\nBotkit-only: Initialization function called automatically when used with Botkit.\n     * Calls createSocketServer to bind a websocket listener to Botkit's pre-existing webserver.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| botkit| any | <br/>\n\n\n\n<a name=\"isConnected\"></a>\n### isConnected()\nIs given user currently connected? Use this to test the websocket connection\nbetween the bot and a given user before sending messages,\nparticularly in cases where a long period of time may have passed.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| user| string | the id of a user, typically from `message.user`<br/>\n\n\n\nExample: `bot.controller.adapter.isConnected(message.user)`\n\n<a name=\"processActivity\"></a>\n### processActivity()\nAccept an incoming webhook request and convert it into a TurnContext which can be processed by the bot's logic.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| req| any | A request object from Restify or Express\n| res| any | A response object from Restify or Express\n| logic|  | A bot logic function in the form `async(context) => { ... }`<br/>\n\n\n\n<a name=\"sendActivities\"></a>\n### sendActivities()\nStandard BotBuilder adapter method to send a message from the bot to the messaging API.\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#sendactivities).\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| context| TurnContext | A TurnContext representing the current incoming message and environment. (not used)\n| activities|  | An array of outgoing activities to be sent back to the messaging API.<br/>\n\n\n\n\n\n"
  },
  {
    "path": "packages/docs/reference/webex.md",
    "content": "# Botkit for Webex Teams Class Reference\n\n[&larr; Botkit Documentation](../core.md) [&larr; Class Index](index.md) \n\nThis is a class reference for all the methods exposed by the [botbuilder-adapter-webex](https://github.com/howdyai/botkit/tree/master/packages/botbuilder-adapter-webex) package.\n\n## Classes\n\n\n* <a href=\"#WebexAdapter\" aria-current=\"page\">WebexAdapter</a>\n* <a href=\"#WebexBotWorker\" aria-current=\"page\">WebexBotWorker</a>\n\n## Interfaces\n\n* <a href=\"#WebexAdapterOptions\" aria-current=\"page\">WebexAdapterOptions</a>\n\n---\n\n<a name=\"WebexAdapter\"></a>\n## WebexAdapter\nConnect [Botkit](https://www.npmjs.com/package/botkit) or [BotBuilder](https://www.npmjs.com/package/botbuilder) to Webex Teams.\n\nTo use this class in your application, first install the package:\n```bash\nnpm install --save botbuilder-adapter-webex\n```\n\nThen import this and other classes into your code:\n```javascript\nconst { WebexAdapter } = require('botbuilder-adapter-webex');\n```\n\nThis class includes the following methods:\n* [continueConversation()](#continueConversation)\n* [deleteActivity()](#deleteActivity)\n* [getIdentity()](#getIdentity)\n* [init()](#init)\n* [processActivity()](#processActivity)\n* [registerAdaptiveCardWebhookSubscription()](#registerAdaptiveCardWebhookSubscription)\n* [registerWebhookSubscription()](#registerWebhookSubscription)\n* [resetWebhookSubscriptions()](#resetWebhookSubscriptions)\n* [sendActivities()](#sendActivities)\n\n\n\n### Create a new WebexAdapter()\n**Parameters**\n\n| Argument | Type | Description\n|--- |--- |---\n| config | [WebexAdapterOptions](#WebexAdapterOptions) | \n\nCreate a Webex adapter. See [WebexAdapterOptions](#webexadapteroptions) for a full definition of the allowed parameters.\n\nUse with Botkit:\n```javascript\nconst adapter = new WebexAdapter({\n     access_token: process.env.ACCESS_TOKEN, // access token from https://developer.webex.com\n     public_address: process.env.PUBLIC_ADDRESS,  // public url of this app https://myapp.com/\n     secret: process.env.SECRET // webhook validation secret - you can define this yourself\n});\nconst controller = new Botkit({\n     adapter: adapter,\n     // ... other configuration options\n});\n```\n\nUse with BotBuilder:\n```javascript\nconst adapter = new WebexAdapter({\n     access_token: process.env.ACCESS_TOKEN, // access token from https://developer.webex.com\n     public_address: process.env.PUBLIC_ADDRESS,  // public url of this app https://myapp.com/\n     secret: process.env.SECRET // webhook validation secret - you can define this yourself\n});\n\n// set up restify...\nconst server = restify.createServer();\nserver.use(restify.plugins.bodyParser());\n// register the webhook subscription to start receiving messages - Botkit does this automatically!\nadapter.registerWebhookSubscription('/api/messages');\n// Load up the bot's identity, otherwise it won't know how to filter messages from itself\nadapter.getIdentity();\n// create an endpoint for receiving messages\nserver.post('/api/messages', (req, res) => {\n     adapter.processActivity(req, res, async(context) => {\n         // do your bot logic here!\n     });\n});\n```\n\n\n\n## Properties and Accessors\n\n| Name | Type | Description\n|--- |--- |---\n| identity |  | Returns the identity of the bot, including {id, emails, displayName, created} and anything else from [this spec](https://webex.github.io/spark-js-sdk/api/#personobject)\n\n## WebexAdapter Class Methods\n<a name=\"continueConversation\"></a>\n### continueConversation()\nStandard BotBuilder adapter method for continuing an existing conversation based on a conversation reference.\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#continueconversation)\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| reference| Partial&lt;ConversationReference&gt; | A conversation reference to be applied to future messages.\n| logic|  | A bot logic function that will perform continuing action in the form `async(context) => { ... }`<br/>\n\n\n\n<a name=\"deleteActivity\"></a>\n### deleteActivity()\nStandard BotBuilder adapter method to delete a previous message.\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#deleteactivity).\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| context| TurnContext | A TurnContext representing the current incoming message and environment. (not used)\n| reference| Partial&lt;ConversationReference&gt; | An object in the form `{activityId: <id of message to delete>, conversation: { id: <id of slack channel>}}`<br/>\n\n\n\n<a name=\"getIdentity\"></a>\n### getIdentity()\nLoad the bot's identity via the Webex API.\nMUST be called by BotBuilder bots in order to filter messages sent by the bot.\n\n\n<a name=\"init\"></a>\n### init()\nBotkit-only: Initialization function called automatically when used with Botkit.\n     * Calls registerWebhookSubscription() during bootup.\n     * Calls getIdentit() to load the bot's identity.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| botkit| any | \n\n\n\n<a name=\"processActivity\"></a>\n### processActivity()\nAccept an incoming webhook request and convert it into a TurnContext which can be processed by the bot's logic.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| req| any | A request object from Restify or Express\n| res| any | A response object from Restify or Express\n| logic|  | A bot logic function in the form `async(context) => { ... }`<br/>\n\n\n\n<a name=\"registerAdaptiveCardWebhookSubscription\"></a>\n### registerAdaptiveCardWebhookSubscription()\nRegister a webhook subscription with Webex Teams to start receiving message events.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| webhook_path| any | the path of the webhook endpoint like `/api/messages`<br/>\n\n\n\n<a name=\"registerWebhookSubscription\"></a>\n### registerWebhookSubscription()\nRegister a webhook subscription with Webex Teams to start receiving message events.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| webhook_path| any | the path of the webhook endpoint like `/api/messages`<br/>\n\n\n\n<a name=\"resetWebhookSubscriptions\"></a>\n### resetWebhookSubscriptions()\nClear out and reset all the webhook subscriptions currently associated with this application.\n\n\n<a name=\"sendActivities\"></a>\n### sendActivities()\nStandard BotBuilder adapter method to send a message from the bot to the messaging API.\n[BotBuilder reference docs](https://docs.microsoft.com/en-us/javascript/api/botbuilder-core/botadapter?view=botbuilder-ts-latest#sendactivities).\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| context| TurnContext | A TurnContext representing the current incoming message and environment.\n| activities|  | An array of outgoing activities to be sent back to the messaging API.<br/>\n\n\n\n\n<a name=\"WebexBotWorker\"></a>\n## WebexBotWorker\nThis is a specialized version of [Botkit's core BotWorker class](core.md#BotWorker) that includes additional methods for interacting with Webex Teams.\nIt includes all functionality from the base class, as well as the extension methods below.\n\nWhen using the WebexAdapter with Botkit, all `bot` objects passed to handler functions will include these extensions.\n\n\nTo use this class in your application, first install the package:\n```bash\nnpm install --save botbuilder-adapter-webex\n```\n\nThen import this and other classes into your code:\n```javascript\nconst { WebexBotWorker } = require('botbuilder-adapter-webex');\n```\n\nThis class includes the following methods:\n* [deleteMessage()](#deleteMessage)\n* [replyInThread()](#replyInThread)\n* [startConversationInRoom()](#startConversationInRoom)\n* [startConversationInThread()](#startConversationInThread)\n* [startPrivateConversation()](#startPrivateConversation)\n\n\n\n\n## Properties and Accessors\n\n| Name | Type | Description\n|--- |--- |---\n| api | Webex | An instance of the [webex api client](https://www.npmjs.com/package/webex)\n\n## WebexBotWorker Class Methods\n<a name=\"deleteMessage\"></a>\n### deleteMessage()\nDelete an existing message.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| update| Partial&lt;BotkitMessage&gt; | An object in the form of `{id: <id of message to delete>}`<br/>\n\n\n\n```javascript\n// send a reply, capture the results\nlet sent = await bot.reply(message,'this is my original reply...');\n\n// delete the sent message using the sent.id field\nawait bot.deleteMessage(sent);\n```\n\n\n<a name=\"replyInThread\"></a>\n### replyInThread()\nLike bot.reply, but as a threaded response to the incoming message rather than a new message in the main channel.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| src| any | an incoming message object\n| resp| any | an outgoing message object (or part of one or just reply text)<br/>\n\n\n\n<a name=\"startConversationInRoom\"></a>\n### startConversationInRoom()\nSwitch a bot's context into a different room.\nAfter calling this method, messages sent with `bot.say` and any dialogs started with `bot.beginDialog` will occur in this new context.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| roomId| string | A Webex rooom id, like one found in `message.channel`\n| userId| string | A Webex user id, like one found in `message.user`<br/>\n\n\n\n```javascript\ncontroller.hears('take this offline', 'message', async(bot, message) => {\n\n     // switch to a different channel\n     await bot.startConversationInRoom(WEBEX_ROOM_ID, message.user);\n\n     // say hello\n     await bot.say('Shall we discuss this matter over here?');\n     // ... continue...\n     await bot.beginDialog(ANOTHER_DIALOG);\n\n});\n```\n\nAlso useful when sending pro-active messages such as those sent on a schedule or in response to external events:\n```javascript\n// Spawn a worker\nlet bot = await controller.spawn();\n\n// Set the context for the bot's next action...\nawait bot.startConversationInRoom(CACHED_ROOM_ID, CACHED_USER_ID);\n\n// Begin a dialog in the 1:1 context\nawait bot.beginDialog(ALERT_DIALOG);\n```\n\n\n<a name=\"startConversationInThread\"></a>\n### startConversationInThread()\nSwitch a bot's context into a specific thread within a room.\nAfter calling this method, messages sent with `bot.say` and any dialogs started with `bot.beginDialog` will occur in this new context.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| roomId| string | A Webex rooom id, like one found in `message.channel`\n| userId| string | A Webex user id, like one found in `message.user`\n| parentId| string | A webex message id that should be the parent message, like the one found in `message.id`<br/>\n\n\n\n```javascript\ncontroller.hears('take this offline', 'message', async(bot, message) => {\n\n     // switch to a different channel\n     await bot.startConversationInThread(WEBEX_ROOM_ID, message.user, message.id);\n\n     // say hello\n     await bot.say('Shall we discuss this matter over here?');\n     // ... continue...\n     await bot.beginDialog(ANOTHER_DIALOG);\n\n});\n```\n\nAlso useful when sending pro-active messages such as those sent on a schedule or in response to external events:\n```javascript\n// Spawn a worker\nlet bot = await controller.spawn();\n\n// Set the context for the bot's next action...\nawait bot.startConversationInRoom(CACHED_ROOM_ID, CACHED_USER_ID);\n\n// Begin a dialog in the 1:1 context\nawait bot.beginDialog(ALERT_DIALOG);\n```\n\n\n<a name=\"startPrivateConversation\"></a>\n### startPrivateConversation()\nChange the context of the _next_ message\nDue to a quirk in the Webex API, we can't know the address of the DM until after sending the first message.\nAs a result, the internal tracking for this conversation can't be persisted properly.\nUSE WITH CAUTION while we try to sort this out.\n\n**Parameters**\n\n| Argument | Type | description\n|--- |--- |---\n| userId| string | user id of a webex teams user, like one from `message.user`<br/>\n\n\n\n\n\n<a name=\"WebexAdapterOptions\"></a>\n## Interface WebexAdapterOptions\n\n\n**Fields**\n\n| Name | Type | Description\n|--- |--- |---\n| access_token | string | An access token for the bot. Get one from [https://developer.webex.com/](https://developer.webex.com/)<br/>\n| enable_incomplete | boolean | Allow the adapter to startup without a complete configuration.<br/>This is risky as it may result in a non-functioning or insecure adapter.<br/>This should only be used when getting started.<br/>\n| public_address | string | The root URL of your bot application.  Something like `https://mybot.com/`<br/>\n| secret | string | Secret used to validate incoming webhooks - you can define this yourself<br/>\n| webhook_name | string | a name for the webhook subscription that will be created to tell Webex to send your bot webhooks.<br/>\n"
  },
  {
    "path": "packages/generator-botkit/CHANGELOG.md",
    "content": "# 4.10.0\n\n* Update to Botkit 4.10\n\n# 4.6.3\n\nFix issue introduced in 4.6.2 that removed required .env file templates\n\n# 4.6.1\n\n* Update all environment variables to UPPER_CASE\n\n# 4.5.1 \n\n* Fix issue the typing indicator sample in the web starter kit\n\n# 4.5.0\n\nUpdate Botkit and Bot Framework package versions to latest\n"
  },
  {
    "path": "packages/generator-botkit/LICENSE.md",
    "content": "Copyright XOXCO, Inc, http://xoxco.com, http://howdy.ai\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "packages/generator-botkit/generators/app/index.js",
    "content": "/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nvar Generator = require('yeoman-generator');\nvar _ = require('underscore');\n_.extend(Generator.prototype, require('yeoman-generator/lib/actions/install'));\n\nvar path = require('path');\n\nconst platforms = [\n    'botframework',\n    'slack',\n    'hangouts',\n    'twilio-sms',\n    'webex',\n    'web',\n    'facebook'\n];\n\nmodule.exports = class extends Generator {\n\n    async prompting() {\n        this.answers = await this.prompt([\n            {\n                type: \"input\",\n                name: \"name\",\n                message: \"What is your bot's name?\",\n                default: this.appname\n            },\n            {\n                type: \"list\",\n                name: \"platform\",\n                choices: platforms,\n                message: \"Which messaging platform?\",\n            },\n            {\n                type: \"input\",\n                name: \"mongo_uri\",\n                message: \"(Optional) Mongo URI for state persistence:\",\n            }\n        ]);\n\n        this.answers.safe_name = this.answers.name.toLowerCase().replace(/\\s+/,'-');\n\n    }\n\n    async composing() {\n        if (this.answers.platform === 'slack') {\n            this.composeWith(require.resolve(path.join(__dirname,'..','slack')), this.answers);\n        } else if (this.answers.platform === 'hangouts') {\n            this.composeWith(require.resolve(path.join(__dirname,'..','hangouts')), this.answers);\n        } else if (this.answers.platform === 'facebook') {\n            this.composeWith(require.resolve(path.join(__dirname,'..','facebook')), this.answers);\n        } else if (this.answers.platform === 'twilio-sms') {\n            this.composeWith(require.resolve(path.join(__dirname,'..','twilio-sms')), this.answers);\n        } else if (this.answers.platform === 'webex') {\n            this.composeWith(require.resolve(path.join(__dirname,'..','webex')), this.answers);\n        } else if (this.answers.platform === 'web') {\n            this.composeWith(require.resolve(path.join(__dirname,'..','web')), this.answers);\n        } else if (this.answers.platform === 'botframework') {\n            this.composeWith(require.resolve(path.join(__dirname,'..','botframework')), this.answers);\n        }\n    }\n\n    writing() {\n\n        this.fs.copyTpl(\n            this.templatePath('package.json'),\n            this.destinationPath('package.json'),\n            this.answers\n        );\n\n        this.fs.copyTpl(\n            this.templatePath('bot.js'),\n            this.destinationPath('bot.js'),\n            this.answers\n        );\n\n        this.fs.copyTpl(\n            this.templatePath('gitignore'),\n            this.destinationPath('.gitignore'),\n            this.answers\n        );\n\n        this.fs.copyTpl(\n            this.templatePath('readme.md'),\n            this.destinationPath('readme.md'),\n            this.answers\n        );\n\n\n        this.fs.copy(\n            this.templatePath('features'),\n            this.destinationPath('features')\n        );\n    }\n\n    install() {\n        this.npmInstall();\n    }\n\n};"
  },
  {
    "path": "packages/generator-botkit/generators/app/templates/bot.js",
    "content": "//  __   __  ___        ___\n// |__) /  \\  |  |__/ |  |  \n// |__) \\__/  |  |  \\ |  |  \n\n// This is the main file for the <%= name %> bot.\n\n// Import Botkit's core features\nconst { Botkit } = require('botkit');\nconst { BotkitCMSHelper } = require('botkit-plugin-cms');\n\n// Import a platform-specific adapter for <%= platform %>.\n<% if (platform === 'slack') { %>\nconst { SlackAdapter, SlackMessageTypeMiddleware, SlackEventMiddleware } = require('botbuilder-adapter-slack');\n<% } else if (platform === 'webex') { %>\nconst { WebexAdapter } = require('botbuilder-adapter-webex');\n<% } else if (platform === 'web') { %>\nconst { WebAdapter } = require('botbuilder-adapter-web');\n<% } else if (platform === 'facebook') { %>\nconst { FacebookAdapter, FacebookEventTypeMiddleware } = require('botbuilder-adapter-facebook');\n<% } else if (platform === 'twilio-sms') { %>const { TwilioAdapter } = require('botbuilder-adapter-twilio-sms');\n<% } else if (platform === 'hangouts') { %>const { HangoutsAdapter } = require('botbuilder-adapter-hangouts');<% } %>\nconst { MongoDbStorage } = require('botbuilder-storage-mongodb');\n\n// Load process.env values from .env file\nrequire('dotenv').config();\n\nlet storage = null;\nif (process.env.MONGO_URI) {\n    storage = mongoStorage = new MongoDbStorage({\n        url : process.env.MONGO_URI,\n    });\n}\n\n<% if (platform === 'slack') { %>\n\nconst adapter = new SlackAdapter({\n    // REMOVE THIS OPTION AFTER YOU HAVE CONFIGURED YOUR APP!\n    enable_incomplete: true,\n\n    // parameters used to secure webhook endpoint\n    verificationToken: process.env.VERIFICATION_TOKEN,\n    clientSigningSecret: process.env.CLIENT_SIGNING_SECRET,  \n\n    // auth token for a single-team app\n    botToken: process.env.BOT_TOKEN,\n\n    // credentials used to set up oauth for multi-team apps\n    clientId: process.env.CLIENT_ID,\n    clientSecret: process.env.CLIENT_SECRET,\n    scopes: ['bot'], \n    redirectUri: process.env.REDIRECT_URI,\n \n    // functions required for retrieving team-specific info\n    // for use in multi-team apps\n    getTokenForTeam: getTokenForTeam,\n    getBotUserByTeam: getBotUserByTeam,\n});\n\n// Use SlackEventMiddleware to emit events that match their original Slack event types.\nadapter.use(new SlackEventMiddleware());\n\n// Use SlackMessageType middleware to further classify messages as direct_message, direct_mention, or mention\nadapter.use(new SlackMessageTypeMiddleware());\n<% } else if (platform === 'webex') { %>\nconst adapter = new WebexAdapter({\n    // REMOVE THIS OPTION AFTER YOU HAVE CONFIGURED YOUR APP!\n    enable_incomplete: true,\n\n    \n    access_token: process.env.ACCESS_TOKEN,\n    public_address: process.env.PUBLIC_ADDRESS\n})    \n<% } else if (platform === 'web') { %>\nconst adapter = new WebAdapter({});\n<% } else if (platform === 'facebook') { %>\nconst adapter = new FacebookAdapter({\n\n    // REMOVE THIS OPTION AFTER YOU HAVE CONFIGURED YOUR APP!\n    enable_incomplete: true,\n\n    verify_token: process.env.FACEBOOK_VERIFY_TOKEN,\n    access_token: process.env.FACEBOOK_ACCESS_TOKEN,\n    app_secret: process.env.FACEBOOK_APP_SECRET,\n})\n\n// emit events based on the type of facebook event being received\nadapter.use(new FacebookEventTypeMiddleware());\n<% } else if (platform === 'twilio-sms') { %>\nconst adapter = new TwilioAdapter({\n\n    // REMOVE THIS OPTION AFTER YOU HAVE CONFIGURED YOUR APP!\n    enable_incomplete: true,\n\n    twilio_number: process.env.TWILIO_NUMBER,\n    account_sid: process.env.TWILIO_ACCOUNT_SID,\n    auth_token: process.env.TWILIO_AUTH_TOKEN,\n});\n<% } else if (platform === 'hangouts') { %>\nconst adapter = new HangoutsAdapter({\n    // REMOVE THIS OPTION AFTER YOU HAVE CONFIGURED YOUR APP!\n    enable_incomplete: true,\n\n    token: process.env.GOOGLE_TOKEN,\n    google_auth_params: {\n        credentials: JSON.parse(process.env['GOOGLE_CREDS'])\n    }\n});\n<% } else { %>\n\n<% } %>\n\nconst controller = new Botkit({\n    webhook_uri: '/api/messages',\n<% if (platform === 'botframework') { %>\n    adapterConfig: {\n        appId: process.env.APP_ID,\n        appPassword: process.env.APP_PASSWORD,\n    },\n<% } else { %>\n    adapter: adapter,\n<% } %>\n    storage\n});\n\nif (process.env.CMS_URI) {\n    controller.usePlugin(new BotkitCMSHelper({\n        uri: process.env.CMS_URI,\n        token: process.env.CMS_TOKEN,\n    }));\n}\n\n// Once the bot has booted up its internal services, you can use them to do stuff.\ncontroller.ready(() => {\n\n    // load traditional developer-created local custom feature modules\n    controller.loadModules(__dirname + '/features');\n\n    /* catch-all that uses the CMS to trigger dialogs */\n    if (controller.plugins.cms) {\n        controller.on('message,direct_message', async (bot, message) => {\n            let results = false;\n            results = await controller.plugins.cms.testTrigger(bot, message);\n\n            if (results !== false) {\n                // do not continue middleware!\n                return false;\n            }\n        });\n    }\n\n});\n\n<% if (platform !== 'web') { %>\n\ncontroller.webserver.get('/', (req, res) => {\n\n    res.send(`This app is running Botkit ${ controller.version }.`);\n\n});\n\n<% } %>\n\n\n<% if (platform === 'slack') { %>\n\ncontroller.webserver.get('/install', (req, res) => {\n    // getInstallLink points to slack's oauth endpoint and includes clientId and scopes\n    res.redirect(controller.adapter.getInstallLink());\n});\n\ncontroller.webserver.get('/install/auth', async (req, res) => {\n    try {\n        const results = await controller.adapter.validateOauthCode(req.query.code);\n\n        console.log('FULL OAUTH DETAILS', results);\n\n        // Store token by team in bot state.\n        tokenCache[results.team_id] = results.bot.bot_access_token;\n\n        // Capture team to bot id\n        userCache[results.team_id] =  results.bot.bot_user_id;\n\n        res.json('Success! Bot installed.');\n\n    } catch (err) {\n        console.error('OAUTH ERROR:', err);\n        res.status(401);\n        res.send(err.message);\n    }\n});\n\nlet tokenCache = {};\nlet userCache = {};\n\nif (process.env.TOKENS) {\n    tokenCache = JSON.parse(process.env.TOKENS);\n} \n\nif (process.env.USERS) {\n    userCache = JSON.parse(process.env.USERS);\n} \n\nasync function getTokenForTeam(teamId) {\n    if (tokenCache[teamId]) {\n        return new Promise((resolve) => {\n            setTimeout(function() {\n                resolve(tokenCache[teamId]);\n            }, 150);\n        });\n    } else {\n        console.error('Team not found in tokenCache: ', teamId);\n    }\n}\n\nasync function getBotUserByTeam(teamId) {\n    if (userCache[teamId]) {\n        return new Promise((resolve) => {\n            setTimeout(function() {\n                resolve(userCache[teamId]);\n            }, 150);\n        });\n    } else {\n        console.error('Team not found in userCache: ', teamId);\n    }\n}\n<% } %>\n"
  },
  {
    "path": "packages/generator-botkit/generators/app/templates/features/sample_echo.js",
    "content": "/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nmodule.exports = function(controller) {\n\n    controller.hears('sample','message,direct_message', async(bot, message) => {\n        await bot.reply(message, 'I heard a sample message.');\n    });\n\n    controller.on('message,direct_message', async(bot, message) => {\n        await bot.reply(message, `Echo: ${ message.text }`);\n    });\n\n}\n"
  },
  {
    "path": "packages/generator-botkit/generators/app/templates/features/sample_hears.js",
    "content": "/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\nmodule.exports = function(controller) {\n\n    // use a function to match a condition in the message\n    controller.hears(async (message) => message.text && message.text.toLowerCase() === 'foo', ['message'], async (bot, message) => {\n        await bot.reply(message, 'I heard \"foo\" via a function test');\n    });\n\n    // use a regular expression to match the text of the message\n    controller.hears(new RegExp(/^\\d+$/), ['message','direct_message'], async function(bot, message) {\n        await bot.reply(message,{ text: 'I heard a number using a regular expression.' });\n    });\n\n    // match any one of set of mixed patterns like a string, a regular expression\n    controller.hears(['allcaps', new RegExp(/^[A-Z\\s]+$/)], ['message','direct_message'], async function(bot, message) {\n        await bot.reply(message,{ text: 'I HEARD ALL CAPS!' });\n    });\n\n}"
  },
  {
    "path": "packages/generator-botkit/generators/app/templates/gitignore",
    "content": ".env\nnode_modules/"
  },
  {
    "path": "packages/generator-botkit/generators/app/templates/package.json",
    "content": "{\n    \"name\": \"botkit-<%= safe_name %>\",\n    \"version\": \"1.0.0\",\n    \"description\": \"\",\n    \"main\": \"bot.js\",\n    \"scripts\": {\n      \"start\": \"node bot.js\",\n      \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n    },\n    \"dependencies\": {\n      \"botkit\": \"^4.15.0\",\n      \"botkit-plugin-cms\": \"^1.0.3\",\n      \"botbuilder-storage-mongodb\":\"^0.9.5\",\n      \"dotenv\": \"^7.0.0\"\n    }\n  }\n  \n"
  },
  {
    "path": "packages/generator-botkit/generators/app/templates/readme.md",
    "content": "# Botkit Starter Kit\n\nThis is a Botkit starter kit for <%= platform %>, created with the [Yeoman generator](https://github.com/howdyai/botkit/tree/master/packages/generator-botkit#readme).\n\nTo complete the configuration of this bot, make sure to update the included `.env` file with your platform tokens and credentials.\n\n[Botkit Docs](https://github.com/howdyai/botkit/blob/main/packages/docs/index.md)\n\nThis bot is powered by [a folder full of modules](https://github.com/howdyai/botkit/blob/main/packages/docs/core.md#organize-your-bot-code). \nEdit the samples, and add your own in the [features/](features/) folder.\n"
  },
  {
    "path": "packages/generator-botkit/generators/botframework/index.js",
    "content": "var Generator = require('yeoman-generator');\n\nmodule.exports = class extends Generator {\n    async prompting() {\n\n        this.platform = await this.prompt([\n            {\n                type: \"input\",\n                name: \"appId\",\n                message: \"App ID\",\n            },\n            {\n                type: \"input\",\n                name: \"appPassword\",\n                message: \"App Password\",\n            }\n        ]);\n\n    }\n    writing() {\n\n        this.fs.copy(\n            this.templatePath('features'),\n            this.destinationPath('features')\n        );\n\n        this.fs.copyTpl(\n            this.templatePath('.env'),\n            this.destinationPath('.env'),\n            { \n                platform: this.platform,\n                options: this.options,\n            },\n        );\n\n    }\n\n    install() {\n        // noop\n    }\n\n};"
  },
  {
    "path": "packages/generator-botkit/generators/botframework/templates/features/botframework_features.js",
    "content": "/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nmodule.exports = function(controller) {\n\n    // send welcome\n    controller.on('conversationUpdate', async(bot, message) => {\n\n\n    });\n\n}"
  },
  {
    "path": "packages/generator-botkit/generators/facebook/index.js",
    "content": "/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\n var Generator = require('yeoman-generator');\n var _ = require('underscore');\n _.extend(Generator.prototype, require('yeoman-generator/lib/actions/install'));\n\nmodule.exports = class extends Generator {\n    async prompting() {\n\n        this.platform = await this.prompt([\n            {\n                type: \"input\",\n                name: \"appId\",\n                message: \"App ID\",\n            },\n            {\n                type: \"input\",\n                name: \"appSecret\",\n                message: \"App Secret\",\n            },\n            {\n                type: \"input\",\n                name: \"access_token\",\n                message: \"Page Access Token\",\n            },\n            {\n                type: \"input\",\n                name: \"verify_token\",\n                message: \"Webhook Verify Token\",\n            },\n        ]);\n\n    }\n    writing() {\n\n        this.fs.copy(\n            this.templatePath('features'),\n            this.destinationPath('features')\n        );\n\n        this.fs.copyTpl(\n            this.templatePath('.env'),\n            this.destinationPath('.env'),\n            { \n                platform: this.platform,\n                options: this.options,\n            },\n        );\n\n    }\n\n    install() {\n        this.npmInstall(['botbuilder-adapter-facebook@latest']);\n    }\n\n};"
  },
  {
    "path": "packages/generator-botkit/generators/facebook/templates/features/facebook_features.js",
    "content": "/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nmodule.exports = function(controller) {\n\n    /**\n     * Detect when a message has a sticker attached\n     */\n    controller.hears(async(message) => message.sticker_id, 'message', async(bot, message) => {\n        await bot.reply(message,'Cool sticker.');\n    });\n\n    controller.on('facebook_postback', async(bot, message) => {\n        await bot.reply(message,`I heard you posting back a post_back about ${ message.text }`);\n    });\n\n\n}"
  },
  {
    "path": "packages/generator-botkit/generators/hangouts/index.js",
    "content": "/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\n var Generator = require('yeoman-generator');\n var _ = require('underscore');\n _.extend(Generator.prototype, require('yeoman-generator/lib/actions/install'));\n\nmodule.exports = class extends Generator {\n\n    async prompting() {\n\n        this.platform = await this.prompt([\n            {\n                type: \"input\",\n                name: \"creds\",\n                message: \"JSON credentials\",\n            },\n            {\n                type: \"input\",\n                name: \"token\",\n                message: \"Token\",\n            },\n        ]);\n\n    }\n\n    writing() {\n\n        this.fs.copy(\n            this.templatePath('features'),\n            this.destinationPath('features')\n        );\n\n\n        this.fs.copyTpl(\n            this.templatePath('.env'),\n            this.destinationPath('.env'),\n            { \n                platform: this.platform,\n                options: this.options,\n            },\n        );\n\n    }\n\n    install() {\n        this.npmInstall(['botbuilder-adapter-hangouts@latest']);\n    }\n\n};"
  },
  {
    "path": "packages/generator-botkit/generators/hangouts/templates/features/hangouts_features.js",
    "content": "/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nmodule.exports = function(controller) {\n\n    controller.on('direct_message', async(bot, message) => {\n        await bot.reply(message,'I heard a private message');\n    });\n\n    controller.on('message', async(bot, message) => {\n        await bot.reply(message,'I heard a public message');\n    });\n\n    controller.on('bot_room_join', async(bot, message) => {\n        await bot.reply(message,'I just joined this room!');\n    });\n\n    controller.hears('thread dialog', ['message','direct_message'], async(bot, message) => {\n        await bot.startConversationInThread(message.channel, message.user);\n        await bot.beginDialog('waterfall_sample');\n    });\n\n    controller.hears('thread', ['message','direct_message'], async(bot, message) => {\n        await bot.replyInThread(message,'This is a new thread!');\n    });\n\n    controller.hears('update', ['message','direct_message'], async(bot, message) => {\n        const reply = await bot.reply(message,'This message will get updated in a few seconds.');\n        setTimeout(async function() {\n            await bot.updateMessage({\n                text: '[ this message was update ]',\n                id: reply.id\n            });\n        }, 3000);\n    });\n\n    controller.hears('delete', ['message','direct_message'], async(bot, message) => {\n        const reply = await bot.reply(message,'This message will get deleted in a few seconds.');\n        setTimeout(async function() {\n            await bot.deleteMessage(reply);\n            await bot.reply(message,'A message was deleted!');\n        }, 3000);\n    });\n\n\n    controller.hears('cards', ['message','direct_message'], async(bot, message) => {\n        bot.reply(message,{\n            cards: [\n                {\n                    \"sections\": [\n                        {\n                            \"widgets\": [\n                                {\n                                    \"image\": { \"imageUrl\": \"https://image.slidesharecdn.com/botkitsignal-160526164159/95/build-a-bot-with-botkit-1-638.jpg?cb=1464280993\" }\n                                },\n                                {\n                                    \"buttons\": [\n                                        {\n                                            \"textButton\": {\n                                                \"text\": \"Open Link\",\n                                                \"onClick\": {\n                                                    \"openLink\": {\n                                                        \"url\": \"https://botkit.ai/docs/\"\n                                                    }\n                                                }\n                                            }\n                                        },\n                                        {\n                                            \"textButton\": {\n                                                \"text\": \"Reply with New\",\n                                                \"onClick\": {\n                                                    \"action\": {\n                                                        \"actionMethodName\": \"new\",\n                                                        \"parameters\": [\n                                                            {\n                                                                \"key\":\"foo\",\n                                                                \"value\": \"bar\"\n                                                            }\n                                                        ]\n                                                    }\n                                                }\n                                            }\n                                        },\n                                        {\n                                            \"textButton\": {\n                                                \"text\": \"Reply with Update\",\n                                                \"onClick\": {\n                                                    \"action\": {\n                                                        \"actionMethodName\": \"update\",\n                                                        \"parameters\": [\n                                                            {\n                                                                \"key\":\"foo\",\n                                                                \"value\": \"bar\"\n                                                            }\n                                                        ]\n                                                    }\n                                                }\n                                            }\n                                        }\n                                    ]\n                                }\n                            ]\n                        }\n                    ]\n                }\n            ]\n        });\n    });\n    \n    controller.on('card_clicked', async(bot, message) => {\n\n        // send a sync reply\n        if (message.action.actionMethodName === 'new') {\n            await bot.replyWithNew(message, 'Card clicked, so I sent a new message.');\n        } else if (message.action.actionMethodName === 'update') {\n            await bot.replyWithUpdate(message, '[ This message was updated after a card click. ]');\n        }\n\n        // send a normal async reply\n        await bot.reply(message,'I got a click.');\n\n    });\n\n    controller.hears('proactive', ['message','direct_message'], async(bot, message) => {\n\n        // capture reference\n        const reference = message.reference;\n        await bot.reply(message,'I will pick this up in a little while...');\n\n        setTimeout(async function() {\n\n            const foo = await controller.spawn();\n            await foo.changeContext(reference);\n            await foo.say('OK I WAITED.');\n\n        }, 10000);\n\n    });\n\n}"
  },
  {
    "path": "packages/generator-botkit/generators/slack/index.js",
    "content": "/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\nvar Generator = require('yeoman-generator');\nvar _ = require('underscore');\n_.extend(Generator.prototype, require('yeoman-generator/lib/actions/install'));\n\nmodule.exports = class extends Generator {\n\n    async prompting() {\n\n        var type = await this.prompt([\n            {\n                type: \"input\",\n                name: \"clientSigningSecret\",\n                message: \"Client signing secret (from api.slack.com)\",\n            },\n            {\n                type: \"list\",\n                name: \"type\",\n                choices: ['single','multi'],\n                message: \"Configure for single-team or multi-team?\",\n            }\n        ]);\n\n        if (type.type == 'single') {\n            this.platform = await this.prompt([\n                {\n                    type: \"input\",\n                    name: \"botToken\",\n                    message: \"Bot Token\",\n                },\n            ]);\n        } else {\n            this.platform = await this.prompt([\n                {\n                    type: \"input\",\n                    name: \"clientId\",\n                    message: \"Client ID\",\n                },\n                {\n                    type: \"input\",\n                    name: \"clientSecret\",\n                    message: \"Client Secret\",\n                },\n                {\n                    type: \"input\",\n                    name: \"redirectUri\",\n                    message: \"OAuth Redirect URI (in the form https://<myhost.com>/install/auth)\",\n                },\n            ]);\n        }\n\n        this.platform.type = type.type;\n        this.platform.clientSigningSecret = type.clientSigningSecret;\n    }\n\n    writing() {\n\n        this.fs.copy(\n            this.templatePath('features'),\n            this.destinationPath('features')\n        );\n\n        this.fs.copyTpl(\n            this.templatePath('.env'),\n            this.destinationPath('.env'),\n            { \n                platform: this.platform,\n                options: this.options,\n            },\n        );\n\n    }\n\n    install() {\n        this.npmInstall(['botbuilder-adapter-slack@latest']);\n    }\n\n};"
  },
  {
    "path": "packages/generator-botkit/generators/slack/templates/features/routes_oauth.js",
    "content": "/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n/**\n * This module implements the oauth routes needed to install an app\n */\nmodule.exports = function(controller) {\n    // controller.webserver.get('/install', (req, res) => {\n    //     // getInstallLink points to slack's oauth endpoint and includes clientId and scopes\n    //     res.redirect(controller.adapter.getInstallLink());\n    // });\n\n    // controller.webserver.get('/install/auth', async (req, res) => {\n    //     try {\n    //         const results = await controller.adapter.validateOauthCode(req.query.code);\n\n    //         console.log('FULL OAUTH DETAILS', results);\n\n    //         // Store token by team in bot state.\n    //         tokenCache[results.team_id] = results.bot.bot_access_token;\n\n    //         // Capture team to bot id\n    //         userCache[results.team_id] =  results.bot.bot_user_id;\n\n    //         res.json('Success! Bot installed.');\n\n    //     } catch (err) {\n    //         console.error('OAUTH ERROR:', err);\n    //         res.status(401);\n    //         res.send(err.message);\n    //     }\n    // });\n};\n\n/**\n * This is a placeholder implementation for getTokenForTeam and getBotUserByTeam\n * TODO: how to expose these to botkit tho?\n */\nlet tokenCache = {};\nlet userCache = {};\n\nif (process.env.TOKENS) {\n    tokenCache = JSON.parse(process.env.TOKENS);\n} \n\nif (process.env.USERS) {\n    userCache = JSON.parse(process.env.USERS);\n} \n\nasync function getTokenForTeam(teamId) {\n    if (tokenCache[teamId]) {\n        return new Promise((resolve) => {\n            setTimeout(function() {\n                resolve(tokenCache[teamId]);\n            }, 150);\n        });\n    } else {\n        console.error('Team not found in tokenCache: ', teamId);\n    }\n}\n\nasync function getBotUserByTeam(teamId) {\n    if (userCache[teamId]) {\n        return new Promise((resolve) => {\n            setTimeout(function() {\n                resolve(userCache[teamId]);\n            }, 150);\n        });\n    } else {\n        console.error('Team not found in userCache: ', teamId);\n    }\n}\n"
  },
  {
    "path": "packages/generator-botkit/generators/slack/templates/features/slack_features.js",
    "content": "/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\nconst { SlackDialog } = require('botbuilder-adapter-slack');\n\nmodule.exports = function(controller) {\n\n    controller.ready(async () => {\n        if (process.env.MYTEAM) {\n            let bot = await controller.spawn(process.env.MYTEAM);\n            await bot.startConversationInChannel(process.env.MYCHAN,process.env.MYUSER);\n            bot.say('I AM AWOKEN.');\n        }\n    });\n\n    controller.on('direct_message', async(bot, message) => {\n        await bot.reply(message,'I heard a private message');\n    });\n\n    controller.hears('dm me', 'message', async(bot, message) => {\n        await bot.startPrivateConversation(message.user);\n        await bot.say(`Let's talk in private.`);\n    });\n\n    controller.on('direct_mention', async(bot, message) => {\n        await bot.reply(message, `I heard a direct mention that said \"${ message.text }\"`);\n    });\n\n    controller.on('mention', async(bot, message) => {\n        await bot.reply(message, `You mentioned me when you said \"${ message.text }\"`);\n    });\n\n    controller.hears('ephemeral', 'message,direct_message', async(bot, message) => {\n        await bot.replyEphemeral(message,'This is an ephemeral reply sent using bot.replyEphemeral()!');\n    });\n\n    controller.hears('threaded', 'message,direct_message', async(bot, message) => {\n        await bot.replyInThread(message,'This is a reply in a thread!');\n\n        await bot.startConversationInThread(message.channel, message.user, message.incoming_message.channelData.ts);\n        await bot.say('And this should also be in that thread!');\n    });\n\n    controller.hears('blocks', 'message', async(bot, message) => {\n\n        await bot.reply(message,{\n            blocks: [\n                {\n                    \"type\": \"section\",\n                    \"text\": {\n                        \"type\": \"mrkdwn\",\n                        \"text\": \"Hello, Assistant to the Regional Manager Dwight! *Michael Scott* wants to know where you'd like to take the Paper Company investors to dinner tonight.\\n\\n *Please select a restaurant:*\"\n                    }\n                },\n                {\n                    \"type\": \"divider\"\n                },\n                {\n                    \"type\": \"section\",\n                    \"text\": {\n                        \"type\": \"mrkdwn\",\n                        \"text\": \"*Farmhouse Thai Cuisine*\\n:star::star::star::star: 1528 reviews\\n They do have some vegan options, like the roti and curry, plus they have a ton of salad stuff and noodles can be ordered without meat!! They have something for everyone here\"\n                    },\n                    \"accessory\": {\n                        \"type\": \"image\",\n                        \"image_url\": \"https://s3-media3.fl.yelpcdn.com/bphoto/c7ed05m9lC2EmA3Aruue7A/o.jpg\",\n                        \"alt_text\": \"alt text for image\"\n                    }\n                },\n                {\n                    \"type\": \"section\",\n                    \"text\": {\n                        \"type\": \"mrkdwn\",\n                        \"text\": \"*Kin Khao*\\n:star::star::star::star: 1638 reviews\\n The sticky rice also goes wonderfully with the caramelized pork belly, which is absolutely melt-in-your-mouth and so soft.\"\n                    },\n                    \"accessory\": {\n                        \"type\": \"image\",\n                        \"image_url\": \"https://s3-media2.fl.yelpcdn.com/bphoto/korel-1YjNtFtJlMTaC26A/o.jpg\",\n                        \"alt_text\": \"alt text for image\"\n                    }\n                },\n                {\n                    \"type\": \"section\",\n                    \"text\": {\n                        \"type\": \"mrkdwn\",\n                        \"text\": \"*Ler Ros*\\n:star::star::star::star: 2082 reviews\\n I would really recommend the  Yum Koh Moo Yang - Spicy lime dressing and roasted quick marinated pork shoulder, basil leaves, chili & rice powder.\"\n                    },\n                    \"accessory\": {\n                        \"type\": \"image\",\n                        \"image_url\": \"https://s3-media2.fl.yelpcdn.com/bphoto/DawwNigKJ2ckPeDeDM7jAg/o.jpg\",\n                        \"alt_text\": \"alt text for image\"\n                    }\n                },\n                {\n                    \"type\": \"divider\"\n                },\n                {\n                    \"type\": \"actions\",\n                    \"elements\": [\n                        {\n                            \"type\": \"button\",\n                            \"text\": {\n                                \"type\": \"plain_text\",\n                                \"text\": \"Farmhouse\",\n                                \"emoji\": true\n                            },\n                            \"value\": \"Farmhouse\"\n                        },\n                        {\n                            \"type\": \"button\",\n                            \"text\": {\n                                \"type\": \"plain_text\",\n                                \"text\": \"Kin Khao\",\n                                \"emoji\": true\n                            },\n                            \"value\": \"Kin Khao\"\n                        },\n                        {\n                            \"type\": \"button\",\n                            \"text\": {\n                                \"type\": \"plain_text\",\n                                \"text\": \"Ler Ros\",\n                                \"emoji\": true\n                            },\n                            \"value\": \"Ler Ros\"\n                        }\n                    ]\n                }\n            ]\n        });\n\n    });\n\n    controller.on('block_actions', async (bot, message) => {\n        await bot.reply(message, `Sounds like your choice is ${ message.incoming_message.channelData.actions[0].value }`)\n    });\n\n    controller.on('slash_command', async(bot, message) => {\n        if (message.text === 'plain') {\n            await bot.reply(message, 'This is a plain reply');\n        } else if (message.text === 'public') {\n            await bot.replyPublic(message, 'This is a public reply');\n        } else if (message.text === 'private') {\n            await bot.replyPrivate(message, 'This is a private reply');\n        }\n\n        // set http status\n        bot.httpBody({text:'You can send an immediate response using bot.httpBody()'});\n\n    });\n\n    controller.on('interactive_message', async (bot, message) => {\n\n        console.log('INTERACTIVE MESSAGE', message);\n\n        switch(message.actions[0].name) {\n            case 'replace':\n                await bot.replyInteractive(message,'[ A previous message was successfully replaced with this less exciting one. ]');\n                break;\n            case 'dialog':\n                await bot.replyWithDialog(message, new SlackDialog('this is a dialog', '123', 'Submit', [\n                    {\n                        type: 'text',\n                        label: 'Field 1',\n                        name: 'field1',\n                    },\n                    {\n                        type: 'text',\n                        label: 'Field 2',\n                        name: 'field2',\n                    }\n                ]).notifyOnCancel(true).state('foo').asObject());\n                break;\n            default:\n                await bot.reply(message, 'Got a button click!');\n        }\n    });\n\n\n    controller.on('dialog_submission', async (bot, message) => {\n        await bot.reply(message, 'Got a dialog submission');\n\n        // Return an error to Slack\n        bot.dialogError([\n            {\n                \"name\": \"field1\",\n                \"error\": \"there was an error in field1\"\n            }\n        ])\n    });\n\n    controller.on('dialog_cancellation', async (bot, message) => {\n        await bot.reply(message, 'Got a dialog cancellation');\n    });\n\n}"
  },
  {
    "path": "packages/generator-botkit/generators/twilio-sms/index.js",
    "content": "/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\nvar Generator = require('yeoman-generator');\nvar _ = require('underscore');\n_.extend(Generator.prototype, require('yeoman-generator/lib/actions/install'));\n\nmodule.exports = class extends Generator {\n    async prompting() {\n\n        this.platform = await this.prompt([\n            {\n                type: \"input\",\n                name: \"number\",\n                message: \"Phone Number\",\n            },\n            {\n                type: \"input\",\n                name: \"account_sid\",\n                message: \"Account SID\",\n            },\n            {\n                type: \"input\",\n                name: \"auth_token\",\n                message: \"Auth Token\",\n            },\n        ]);\n\n    }\n\n    writing() {\n\n        this.fs.copy(\n            this.templatePath('features'),\n            this.destinationPath('features')\n        );\n\n\n        this.fs.copyTpl(\n            this.templatePath('.env'),\n            this.destinationPath('.env'),\n            { \n                platform: this.platform,\n                options: this.options,\n            },\n        );\n    }\n\n    install() {\n        this.npmInstall(['botbuilder-adapter-twilio-sms@latest']);\n        this.npmInstall(['twilio']);\n    }\n\n};"
  },
  {
    "path": "packages/generator-botkit/generators/twilio-sms/templates/features/twilio_features.js",
    "content": "/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\nconst Twilio = require('twilio');\n\nmodule.exports = function(controller) {\n\n    controller.on('picture_message', async(bot, message) => {\n        bot.reply(message, 'Nice pic!');\n    });\n\n    controller.hears('twiml','message', async(bot, message) => {\n\n        let twiml = new Twilio.twiml.MessagingResponse();\n        twiml.message('This is a message sent using the HTTP response and TWIML');\n        bot.httpBody(twiml.toString());\n        \n    });\n\n}"
  },
  {
    "path": "packages/generator-botkit/generators/web/index.js",
    "content": "/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\n var Generator = require('yeoman-generator');\n var _ = require('underscore');\n _.extend(Generator.prototype, require('yeoman-generator/lib/actions/install'));\n \nmodule.exports = class extends Generator {\n\n    async prompting() {\n\n        this.platform = await this.prompt([\n        ]);\n\n    }\n\n    writing() {\n\n        this.fs.copy(\n            this.templatePath('features'),\n            this.destinationPath('features')\n        );\n\n        this.fs.copy(\n            this.templatePath('public'),\n            this.destinationPath('public')\n        );\n\n        this.fs.copy(\n            this.templatePath('sass'),\n            this.destinationPath('sass')\n        );\n\n        this.fs.copyTpl(\n            this.templatePath('.env'),\n            this.destinationPath('.env'),\n            { \n                platform: this.platform,\n                options: this.options,\n            },\n        );\n    }\n\n    install() {\n        this.npmInstall(['botbuilder-adapter-web@latest']);\n\n        // TODO: Install sass?\n        // TODO: Add build step to package.json\n        // TODO: Add public folder definition in bot.js and/or in a skill somewhere\n        \n    }\n\n};\n"
  },
  {
    "path": "packages/generator-botkit/generators/web/templates/features/chat.js",
    "content": "/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\nconst express = require('express');\nconst path = require('path');\n\nmodule.exports = function(controller) {\n\n    // make public/index.html available as localhost/index.html\n    // by making the /public folder a static/public asset\n    controller.publicFolder('/', path.join(__dirname,'..','public'));\n\n    console.log('Chat with me: http://localhost:' + (process.env.PORT || 3000));\n}"
  },
  {
    "path": "packages/generator-botkit/generators/web/templates/features/typing.js",
    "content": "/**\n * This module demonstrates the use of the typing indicator in a conversation, and when using bot.reply\n * Tell your bot \"typing dialog\" or \"typing reply\" to see this in action.\n */\nconst { BotkitConversation } = require(\"botkit\");\n\nmodule.exports = function(controller) {\n\n    let typing = new BotkitConversation('typing', controller);\n\n    typing.say('I am going to type for a while now...');\n    typing.addAction('typing');\n\n    // start the typing indicator\n    typing.addMessage({type: 'typing'}, 'typing');\n    // trigger a gotoThread, which gives us an opportunity to delay the next message\n    typing.addAction('next_thread','typing');\n\n    typing.addMessage('typed!','next_thread');\n\n    // use the before handler to delay the next message \n    typing.before('next_thread',  async () => {\n        return new Promise((resolve) => {\n            // simulate some long running process\n            setTimeout(resolve, 3000);\n        });\n    });\n\n    controller.addDialog(typing);\n\n    controller.hears('typing dialog', 'message', async (bot, message) => {\n        await bot.beginDialog('typing');\n    });\n\n    controller.hears('typing reply', 'message', async (bot, message) => {\n\n        await bot.reply(message, {type: 'typing'});\n        setTimeout(async () => {\n            // will have to reset context because turn has now ended.\n            await bot.changeContext(message.reference);\n            await bot.reply(message, 'Typed!');\n        }, 1000);\n    });\n};"
  },
  {
    "path": "packages/generator-botkit/generators/web/templates/features/websocket_features.js",
    "content": "/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\nmodule.exports = function(controller) {\n\n    if (controller.adapter.name === 'Web Adapter') {\n\n        console.log('Loading sample web features...');\n\n        controller.hears(new RegExp('quick'), 'message', async (bot, message) => {\n\n            await bot.reply(message,{\n                text: 'Here are some quick replies',\n                quick_replies: [\n                    {\n                        title: 'Foo',\n                        payload: 'foo',\n                    },\n                    {\n                        title: 'Bar',\n                        payload: 'bar',\n                    }\n                ]\n            });\n        });\n\n\n    }\n\n}"
  },
  {
    "path": "packages/generator-botkit/generators/web/templates/public/client.js",
    "content": "/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\nvar converter = new showdown.Converter();\nconverter.setOption('openLinksInNewWindow', true);\n\nvar Botkit = {\n    config: {\n        ws_url: (location.protocol === 'https:' ? 'wss' : 'ws') + '://' + location.host,\n        reconnect_timeout: 3000,\n        max_reconnect: 5,\n        enable_history: false,\n    },\n    options: {\n        use_sockets: true,\n    },\n    reconnect_count: 0,\n    guid: null,\n    current_user: null,\n    on: function (event, handler) {\n        this.message_window.addEventListener(event, function (evt) {\n            handler(evt.detail);\n        });\n    },\n    trigger: function (event, details) {\n        var event = new CustomEvent(event, {\n            detail: details\n        });\n        this.message_window.dispatchEvent(event);\n    },\n    request: function (url, body) {\n        var that = this;\n        return new Promise(function (resolve, reject) {\n            var xmlhttp = new XMLHttpRequest();\n\n            xmlhttp.onreadystatechange = function () {\n                if (xmlhttp.readyState == XMLHttpRequest.DONE) {\n                    if (xmlhttp.status == 200) {\n                        var response = xmlhttp.responseText;\n                        if (response !='') {\n                            var message = null;\n                            try {\n                                message = JSON.parse(response);\n                            } catch (err) {\n                                reject(err);\n                                return;\n                            }\n                            resolve(message);\n                        } else {\n                            resolve([]);\n                        }\n                    } else {\n                        reject(new Error('status_' + xmlhttp.status));\n                    }\n                }\n            };\n\n            xmlhttp.open(\"POST\", url, true);\n            xmlhttp.setRequestHeader(\"Content-Type\", \"application/json\");\n            xmlhttp.send(JSON.stringify(body));\n        });\n\n    },\n    send: function (text, e) {\n        var that = this;\n        if (e) e.preventDefault();\n        if (!text) {\n            return;\n        }\n        var message = {\n            type: 'outgoing',\n            text: text\n        };\n\n        this.clearReplies();\n        that.renderMessage(message);\n\n        that.deliverMessage({\n            type: 'message',\n            text: text,\n            user: this.guid,\n            channel: this.options.use_sockets ? 'websocket' : 'webhook'\n        });\n\n        this.input.value = '';\n\n        this.trigger('sent', message);\n\n        return false;\n    },\n    deliverMessage: function (message) {\n        if (this.options.use_sockets) {\n            this.socket.send(JSON.stringify(message));\n        } else {\n            this.webhook(message);\n        }\n    },\n    getHistory: function (guid) {\n        var that = this;\n        if (that.guid) {\n            that.request('/botkit/history', {\n                user: that.guid\n            }).then(function (history) {\n                if (history.success) {\n                    that.trigger('history_loaded', history.history);\n                } else {\n                    that.trigger('history_error', new Error(history.error));\n                }\n            }).catch(function (err) {\n                that.trigger('history_error', err);\n            });\n        }\n    },\n    webhook: function (message) {\n        var that = this;\n\n        that.request('/api/messages', message).then(function (messages) {\n            messages.forEach((message) => {\n                that.trigger(message.type, message);\n            });\n        }).catch(function (err) {\n            that.trigger('webhook_error', err);\n        });\n\n    },\n    connect: function (user) {\n\n        var that = this;\n\n        if (user && user.id) {\n            Botkit.setCookie('botkit_guid', user.id, 1);\n\n            user.timezone_offset = new Date().getTimezoneOffset();\n            that.current_user = user;\n            console.log('CONNECT WITH USER', user);\n        }\n\n        // connect to the chat server!\n        if (that.options.use_sockets) {\n            that.connectWebsocket(that.config.ws_url);\n        } else {\n            that.connectWebhook();\n        }\n\n    },\n    connectWebhook: function () {\n        var that = this;\n        if (Botkit.getCookie('botkit_guid')) {\n            that.guid = Botkit.getCookie('botkit_guid');\n            connectEvent = 'welcome_back';\n        } else {\n            that.guid = that.generate_guid();\n            Botkit.setCookie('botkit_guid', that.guid, 1);\n        }\n\n        if (this.options.enable_history) {\n            that.getHistory();\n        }\n\n        // connect immediately\n        that.trigger('connected', {});\n        that.webhook({\n            type: connectEvent,\n            user: that.guid,\n            channel: 'webhook',\n        });\n\n    },\n    connectWebsocket: function (ws_url) {\n        var that = this;\n        // Create WebSocket connection.\n        that.socket = new WebSocket(ws_url);\n\n        var connectEvent = 'hello';\n        if (Botkit.getCookie('botkit_guid')) {\n            that.guid = Botkit.getCookie('botkit_guid');\n            connectEvent = 'welcome_back';\n        } else {\n            that.guid = that.generate_guid();\n            Botkit.setCookie('botkit_guid', that.guid, 1);\n        }\n\n        if (this.options.enable_history) {\n            that.getHistory();\n        }\n\n        // Connection opened\n        that.socket.addEventListener('open', function (event) {\n            console.log('CONNECTED TO SOCKET');\n            that.reconnect_count = 0;\n            that.trigger('connected', event);\n            that.deliverMessage({\n                type: connectEvent,\n                user: that.guid,\n                channel: 'socket',\n                user_profile: that.current_user ? that.current_user : null,\n            });\n        });\n\n        that.socket.addEventListener('error', function (event) {\n            console.error('ERROR', event);\n        });\n\n        that.socket.addEventListener('close', function (event) {\n            console.log('SOCKET CLOSED!');\n            that.trigger('disconnected', event);\n            if (that.reconnect_count < that.config.max_reconnect) {\n                setTimeout(function () {\n                    console.log('RECONNECTING ATTEMPT ', ++that.reconnect_count);\n                    that.connectWebsocket(that.config.ws_url);\n                }, that.config.reconnect_timeout);\n            } else {\n                that.message_window.className = 'offline';\n            }\n        });\n\n        // Listen for messages\n        that.socket.addEventListener('message', function (event) {\n            var message = null;\n            try {\n                message = JSON.parse(event.data);\n            } catch (err) {\n                that.trigger('socket_error', err);\n                return;\n            }\n\n            that.trigger(message.type, message);\n        });\n    },\n    clearReplies: function () {\n        this.replies.innerHTML = '';\n    },\n    quickReply: function (payload) {\n        this.send(payload);\n    },\n    focus: function () {\n        this.input.focus();\n    },\n    renderMessage: function (message) {\n        var that = this;\n        if (!that.next_line) {\n            that.next_line = document.createElement('div');\n            that.message_list.appendChild(that.next_line);\n        }\n        if (message.text) {\n            message.html = converter.makeHtml(message.text);\n        }\n\n        that.next_line.innerHTML = that.message_template({\n            message: message\n        });\n        if (!message.isTyping) {\n            delete (that.next_line);\n        }\n    },\n    triggerScript: function (script, thread) {\n        this.deliverMessage({\n            type: 'trigger',\n            user: this.guid,\n            channel: 'socket',\n            script: script,\n            thread: thread\n        });\n    },\n    identifyUser: function (user) {\n\n        user.timezone_offset = new Date().getTimezoneOffset();\n\n        this.guid = user.id;\n        Botkit.setCookie('botkit_guid', user.id, 1);\n\n        this.current_user = user;\n\n        this.deliverMessage({\n            type: 'identify',\n            user: this.guid,\n            channel: 'socket',\n            user_profile: user,\n        });\n    },\n    receiveCommand: function (event) {\n        switch (event.data.name) {\n            case 'trigger':\n                // tell Botkit to trigger a specific script/thread\n                console.log('TRIGGER', event.data.script, event.data.thread);\n                Botkit.triggerScript(event.data.script, event.data.thread);\n                break;\n            case 'identify':\n                // link this account info to this user\n                console.log('IDENTIFY', event.data.user);\n                Botkit.identifyUser(event.data.user);\n                break;\n            case 'connect':\n                // link this account info to this user\n                Botkit.connect(event.data.user);\n                break;\n            default:\n                console.log('UNKNOWN COMMAND', event.data);\n        }\n    },\n    sendEvent: function (event) {\n\n        if (this.parent_window) {\n            this.parent_window.postMessage(event, '*');\n        }\n\n    },\n    setCookie: function (cname, cvalue, exdays) {\n        var d = new Date();\n        d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));\n        var expires = \"expires=\" + d.toUTCString();\n        document.cookie = cname + \"=\" + cvalue + \";\" + expires + \";path=/\";\n    },\n    getCookie: function (cname) {\n        var name = cname + \"=\";\n        var decodedCookie = decodeURIComponent(document.cookie);\n        var ca = decodedCookie.split(';');\n        for (var i = 0; i < ca.length; i++) {\n            var c = ca[i];\n            while (c.charAt(0) == ' ') {\n                c = c.substring(1);\n            }\n            if (c.indexOf(name) == 0) {\n                return c.substring(name.length, c.length);\n            }\n        }\n        return \"\";\n    },\n    generate_guid: function () {\n        function s4() {\n            return Math.floor((1 + Math.random()) * 0x10000)\n                .toString(16)\n                .substring(1);\n        }\n        return s4() + s4() + '-' + s4() + '-' + s4() + '-' +\n            s4() + '-' + s4() + s4() + s4();\n    },\n    boot: function (user) {\n\n        console.log('Booting up');\n\n        var that = this;\n\n\n        that.message_window = document.getElementById(\"message_window\");\n\n        that.message_list = document.getElementById(\"message_list\");\n\n        var source = document.getElementById('message_template').innerHTML;\n        that.message_template = Handlebars.compile(source);\n\n        that.replies = document.getElementById('message_replies');\n\n        that.input = document.getElementById('messenger_input');\n\n        that.focus();\n\n        that.on('connected', function () {\n            that.message_window.className = 'connected';\n            that.input.disabled = false;\n            that.sendEvent({\n                name: 'connected'\n            });\n        })\n\n        that.on('disconnected', function () {\n            that.message_window.className = 'disconnected';\n            that.input.disabled = true;\n        });\n\n        that.on('webhook_error', function (err) {\n\n            alert('Error sending message!');\n            console.error('Webhook Error', err);\n\n        });\n\n        that.on('typing', function () {\n            that.clearReplies();\n            that.renderMessage({\n                isTyping: true\n            });\n        });\n\n        that.on('sent', function () {\n            // do something after sending\n        });\n\n        that.on('message', function (message) {\n\n            console.log('RECEIVED MESSAGE', message);\n            that.renderMessage(message);\n\n        });\n\n        that.on('message', function (message) {\n            if (message.goto_link) {\n                window.location = message.goto_link;\n            }\n        });\n\n\n        that.on('message', function (message) {\n            that.clearReplies();\n            if (message.quick_replies) {\n\n                var list = document.createElement('ul');\n\n                var elements = [];\n                for (var r = 0; r < message.quick_replies.length; r++) {\n                    (function (reply) {\n\n                        var li = document.createElement('li');\n                        var el = document.createElement('a');\n                        el.innerHTML = reply.title;\n                        el.href = '#';\n\n                        el.onclick = function () {\n                            that.quickReply(reply.payload);\n                        }\n\n                        li.appendChild(el);\n                        list.appendChild(li);\n                        elements.push(li);\n\n                    })(message.quick_replies[r]);\n                }\n\n                that.replies.appendChild(list);\n\n                // uncomment this code if you want your quick replies to scroll horizontally instead of stacking\n                // var width = 0;\n                // // resize this element so it will scroll horizontally\n                // for (var e = 0; e < elements.length; e++) {\n                //     width = width + elements[e].offsetWidth + 18;\n                // }\n                // list.style.width = width + 'px';\n\n                if (message.disable_input) {\n                    that.input.disabled = true;\n                } else {\n                    that.input.disabled = false;\n                }\n            } else {\n                that.input.disabled = false;\n            }\n        });\n\n        that.on('history_loaded', function (history) {\n            if (history) {\n                for (var m = 0; m < history.length; m++) {\n                    that.renderMessage({\n                        text: history[m].text,\n                        type: history[m].type == 'message_received' ? 'outgoing' : 'incoming', // set appropriate CSS class\n                    });\n                }\n            }\n        });\n\n\n        if (window.self !== window.top) {\n            // this is embedded in an iframe.\n            // send a message to the master frame to tell it that the chat client is ready\n            // do NOT automatically connect... rather wait for the connect command.\n            that.parent_window = window.parent;\n            window.addEventListener(\"message\", that.receiveCommand, false);\n            that.sendEvent({\n                type: 'event',\n                name: 'booted'\n            });\n            console.log('Messenger booted in embedded mode');\n\n        } else {\n\n            console.log('Messenger booted in stand-alone mode');\n            // this is a stand-alone client. connect immediately.\n            that.connect(user);\n        }\n\n        return that;\n    }\n};\n\n\n(function () {\n    // your page initialization code here\n    // the DOM will be available here\n    Botkit.boot();\n})();"
  },
  {
    "path": "packages/generator-botkit/generators/web/templates/public/css/embed.css",
    "content": "#embedded_messenger {\n  position: fixed;\n  z-index: 1000;\n  bottom: -400px;\n  right: 2rem;\n  height: 434px;\n  transition: 0.5s ease-in-out bottom;\n}\n#embedded_messenger.active {\n  bottom: 0;\n}\n#embedded_messenger iframe {\n  height: 400px;\n  width: 100%;\n  border: 0;\n}\n#embedded_messenger #message_header {\n  background: #000;\n  padding: 0.5rem 1rem;\n  color: #FFF;\n}\n\n/*# sourceMappingURL=embed.css.map */\n"
  },
  {
    "path": "packages/generator-botkit/generators/web/templates/public/css/styles.css",
    "content": "/* shared botkit ui styles */\n* {\n  box-sizing: border-box;\n}\n\nbody,\nhtml {\n  margin: 0;\n  padding: 0;\n  font-size: 18px;\n  background-color: #FFF;\n  font-family: \"helvetica\", sans-serif;\n}\n\n.wrapper {\n  position: relative;\n  max-width: 1000px;\n  margin: 0 auto;\n}\n.wrapper:after {\n  content: \"\";\n  display: table;\n  clear: both;\n}\n\n.box {\n  border: 2px solid #CCC;\n  padding: 1rem calc(1rem - 2px);\n  margin-bottom: 1rem;\n}\n.box:after {\n  content: \"\";\n  display: table;\n  clear: both;\n}\n.box h1,\n.box h2,\n.box h3 {\n  margin-top: 0;\n}\n\nfooter {\n  text-align: center;\n}\n\n.hero {\n  text-align: center;\n  padding: 2rem;\n}\n.hero h1 {\n  font-size: 4rem;\n  margin: 0;\n}\n\na {\n  color: #a795ef;\n}\n\n.copyurl {\n  width: 100%;\n  font-size: 1.25rem;\n}\n\ndiv.input label {\n  font-weight: bold;\n  font-size: smaller;\n}\n\n.addon {\n  display: flex;\n  border: 1px solid #999;\n  border-radius: 6px;\n  padding: 5px;\n  background: #F0F0F0;\n}\n.addon input,\n.addon textarea {\n  flex-grow: 1;\n  border: 0;\n  background: transparent;\n}\n.addon button {\n  flex-grow: 0;\n  background: transparent;\n  border: 1px solid #999;\n  border-radius: 6px;\n  font-weight: bold;\n}\n.addon button.textarea {\n  align-self: flex-start;\n  padding: 0.5rem;\n}\n.addon button:hover {\n  background: #FFF;\n  color: #a795ef;\n}\n\ndiv.hr {\n  border: 1px dashed #ccc;\n  width: 10%;\n  margin: 4rem auto;\n  height: 1px;\n}\n\na.button {\n  border: 2px solid #a795ef;\n  font-weight: bold;\n  margin: 0;\n  border-radius: 3px;\n  display: inline-block;\n  padding: 0.5rem 2rem;\n  text-align: center;\n  text-decoration: none;\n  box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.2);\n  background-color: #FFF;\n  transition: box-shadow 0.1s linear;\n}\na.button:hover {\n  box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.1);\n}\n\n/* chat client */\n#message_window {\n  background: #FFFFFF;\n  border-left: 1px solid #CCC;\n  border-right: 1px solid #CCC;\n  /*height: 500px;\n  width: 320px;*/\n  height: 100%;\n  width: 100%;\n  /*margin: 2rem auto;*/\n  display: flex;\n  flex-direction: column;\n  font-family: \"helvetica\", sans-serif;\n}\n#message_window .disconnected {\n  background: #FFFFCC;\n  padding: 0.25rem;\n}\n#message_window.connected .disconnected {\n  display: none;\n}\n#message_window .offline {\n  display: none;\n}\n#message_window.offline .disconnected {\n  display: none;\n}\n#message_window.offline .offline {\n  background: #FF0000;\n  color: #FFF;\n  padding: 0.25rem;\n  display: block;\n}\n#message_window .powered_by {\n  flex-shrink: 0;\n  text-align: center;\n  border-bottom: 1px solid #CCC;\n  font-size: 14px;\n  padding: 0.25rem;\n  color: #666;\n}\n#message_window .powered_by a {\n  text-decoration: none;\n  color: #666;\n}\n#message_window .powered_by img {\n  position: relative;\n  top: 2px;\n}\n#message_window section {\n  flex-grow: 1;\n  flex-direction: column-reverse;\n  display: flex;\n  overflow-y: auto;\n}\n#message_window section div div {\n  margin: 0.25rem;\n  clear: both;\n}\n#message_window footer {\n  border-top: 1px solid #CCC;\n  padding: 0.25rem;\n}\n#message_window footer input[type=text] {\n  flex-grow: 1;\n  font-size: 1.25rem;\n  outline: none;\n  border: none;\n}\n#message_window footer button {\n  width: 50px;\n  background: none;\n  border: 0;\n  cursor: pointer;\n  color: blue;\n  font-weight: bold;\n}\n#message_window form {\n  display: flex;\n  margin: 0;\n  padding: 0.25rem;\n}\n#message_window #message_template {\n  display: none;\n}\n#message_window .message {\n  font-size: 14px;\n  padding: 0.5rem;\n  background: #F0F0F0;\n  color: #333;\n  border-radius: 5px;\n  width: auto;\n  display: inline-block;\n  max-width: 75%;\n}\n#message_window .file_attachment {\n  background: #F0F0F0;\n  color: #333;\n  border-radius: 5px;\n  display: inline-block;\n  max-width: 75%;\n}\n#message_window .file_attachment img {\n  max-width: 100%;\n  display: block;\n}\n#message_window .button_message {\n  margin: 1rem 0;\n  border-radius: 4px;\n  border-color: orange;\n  border-style: solid;\n  color: orange;\n  border-width: 1px;\n  padding: 0.25rem 1rem;\n  text-decoration: none;\n  text-align: center;\n  box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.25);\n  display: block;\n}\n#message_window .message p {\n  margin-top: 0;\n  margin-bottom: 0.5rem;\n}\n#message_window .message p:last-child {\n  margin-bottom: 0;\n}\n#message_window .message.outgoing {\n  float: right;\n  background: #a795ef;\n  color: white;\n}\n#message_window #message_replies {\n  text-align: center;\n  overflow-x: auto;\n  flex-shrink: 0;\n  -webkit-overflow-scrolling: touch;\n  /* Lets it scroll lazy */\n}\n#message_window #message_replies ul {\n  list-style-type: none;\n  margin: 0px auto;\n  padding: 0;\n}\n#message_window #message_replies ul li {\n  display: inline-block;\n  margin: 0.5rem;\n  margin-left: 0;\n}\n#message_window #message_replies a {\n  text-decoration: none;\n  display: block;\n  border: 1px solid #a795ef;\n  color: #a795ef;\n  border-radius: 16px;\n  padding: 0.25rem 1rem;\n  font-size: 14px;\n  cursor: pointer;\n}\n#message_window #message_replies a:hover {\n  background: #a795ef;\n  color: #FFF;\n}\n\n/* typing indicator CSS based on code by Joseph Fusco -> https://codepen.io/fusco/pen/XbpaYv */\n.typing-indicator {\n  display: table;\n  margin: 0 auto;\n  position: relative;\n}\n.typing-indicator span {\n  height: 5px;\n  width: 5px;\n  float: left;\n  margin: 0 1px;\n  background-color: #333;\n  display: block;\n  border-radius: 50%;\n  opacity: 0.4;\n}\n.typing-indicator span:nth-of-type(1) {\n  animation: 1s blink infinite 0.3333s;\n}\n.typing-indicator span:nth-of-type(2) {\n  animation: 1s blink infinite 0.6666s;\n}\n.typing-indicator span:nth-of-type(3) {\n  animation: 1s blink infinite 0.9999s;\n}\n\n@keyframes blink {\n  50% {\n    opacity: 1;\n  }\n}\n/* special styles for homepage */\n#home {\n  position: relative;\n  max-width: 650px;\n  margin: auto;\n}\n#home:after {\n  content: \"\";\n  display: table;\n  clear: both;\n}\n\n#homepage_bot {\n  width: 400px;\n  height: 450px;\n  float: left;\n  border: 5px solid #333;\n  box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.5);\n}\n#homepage_bot iframe {\n  border: 0;\n  height: 100%;\n  width: 100%;\n}\n\n#welcome {\n  margin-left: 440px;\n}\n\n/*# sourceMappingURL=styles.css.map */\n"
  },
  {
    "path": "packages/generator-botkit/generators/web/templates/public/index.html",
    "content": "<html>\n    <head>\n        <title>Botkit Anywhere</title>\n        <script src=\"https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.10/handlebars.min.js\"></script>\n        <script src=\"https://cdn.rawgit.com/showdownjs/showdown/1.7.4/dist/showdown.min.js\"></script>\n        <link rel=\"stylesheet\" href=\"/css/styles.css\" />\n        <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    </head>\n    <body >\n      <div class=\"wrapper\">\n\n        <div id=\"message_window\">\n            <div class=\"disconnected\">\n                Disconnected... reconnecting!\n            </div>\n            <div class=\"offline\">\n                Offline! Reload to reconnect.\n            </div>\n            <div class=\"powered_by\">\n              Powered by <a href=\"https://github.com/howdyai/botkit\" target=\"_blank\" title=\"Building Blocks for Building Bots\"><img src=\"/botkit_icon.png\" width=\"15\" height=\"15\" alt=\"Botkit Logo\" /> Botkit</a>\n            </div>\n            <section>\n                <div id=\"message_list\">\n                    <div id=\"message_template\">\n                        <div class=\"message {{message.type}}\">\n                            {{#if message.isTyping}}\n                              <div class=\"typing-indicator\">\n                                <span></span>\n                                <span></span>\n                                <span></span>\n                              </div>\n                            {{/if}}\n                            {{{message.html}}}\n\n                            {{#if message.open_link}}\n                              <a href=\"{{{message.open_link}}}\" target=\"_blank\" class=\"button_message\">{{#if message.link_title}}{{message.link_title}}{{else}}{{message.open_link}}{{/if}}</a>\n                            {{/if}}\n                        </div>\n                        {{#message.files}}\n                          <div class=\"file_attachment\">\n                          {{#if image}}\n                            <img src=\"{{{url}}}\" alt=\"{{{url}}}\" />\n                          {{else}}\n                            <a href=\"{{{url}}}\" title=\"{{{url}}}\">{{{url}}}</a>\n                          {{/if}}\n                          </div>\n                        {{/message.files}}\n                    </div>\n                </div>\n            </section>\n            <div id=\"message_replies\">\n            </div>\n            <footer>\n                <form onsubmit=\"Botkit.send(Botkit.input.value, event)\">\n                    <input type=\"text\" autocomplete=\"off\" id=\"messenger_input\" placeholder=\"Type here...\" />\n                    <button type=\"submit\">Send</button>\n                </form>\n            </footer>\n        </div>\n        </div>\n        <script src=\"/client.js\"></script>\n    </body>\n</html>"
  },
  {
    "path": "packages/generator-botkit/generators/web/templates/sass/_botkit.scss",
    "content": "$botkit_purple: #a795ef;\n@mixin clearfix {\n    &:after {\n        content: \"\";\n        display: table;\n        clear: both;\n    }\n}\n\n* {\n    box-sizing: border-box;\n}\n\nbody,\nhtml {\n    margin: 0;\n    padding: 0;\n    font-size: 18px;\n    background-color: #FFF;\n    font-family: 'helvetica', sans-serif;\n}\n\n.wrapper {\n    @include clearfix;\n    position: relative;\n    max-width: 1000px;\n    margin: 0 auto;\n}\n\n.box {\n    @include clearfix;\n    border: 2px solid #CCC;\n    padding: 1rem calc(1rem - 2px);\n    margin-bottom: 1rem;\n\n    h1,\n    h2,\n    h3 {\n        margin-top: 0;\n    }\n}\n\nfooter {\n    text-align: center;\n}\n\n.hero {\n    text-align: center;\n    padding: 2rem;\n\n    h1 {\n        font-size: 4rem;\n        margin: 0;\n\n    }\n}\n\na {\n    color: $botkit_purple;\n}\n\n.copyurl {\n    width: 100%;\n    font-size: 1.25rem;\n}\n\ndiv.input {\n    label {\n        font-weight: bold;\n        font-size: smaller;\n    }\n}\n\n.addon {\n    display: flex;\n    border: 1px solid #999;\n    border-radius: 6px;\n    padding: 5px;\n    background: #F0F0F0;\n\n    input,\n    textarea {\n        flex-grow: 1;\n        border: 0;\n        background: transparent;\n    }\n\n    button {\n        flex-grow: 0;\n        background: transparent;\n        border: 1px solid #999;\n        border-radius: 6px;\n        font-weight: bold;\n\n        &.textarea {\n            align-self: flex-start;\n            padding: 0.5rem;\n        }\n\n        &:hover {\n            background: #FFF;\n            color: $botkit_purple;\n        }\n    }\n}\n\ndiv.hr {\n    border: 1px dashed #ccc;\n    width: 10%;\n    margin: 4rem auto;\n    height: 1px;\n}\n\na.button {\n    border: 2px solid $botkit_purple;\n    font-weight: bold;\n    // font-size: 4rem;\n    margin: 0;\n    border-radius: 3px;\n    display: inline-block;\n    padding: 0.5rem 2rem;\n    text-align: center;\n    text-decoration: none;\n    // color: #FFF;\n    box-shadow: 5px 5px 5px rgba(0,0,0,0.2);\n    background-color: #FFF;\n    transition: box-shadow 0.1s linear;\n\n    &:hover {\n        // background-color: rgba($botkit_purple, 0.1);\n        box-shadow: 1px 1px 5px rgba(0,0,0,0.1);\n    }\n}\n"
  },
  {
    "path": "packages/generator-botkit/generators/web/templates/sass/_chat.scss",
    "content": "$action_color: orange;\n$background: #FFFFFF;\n$bot_message_background: #F0F0F0;\n$bot_message_text: #333;\n$human_message_background: $botkit_purple;\n$human_message_text: white;\n\n#message_window {\n    background: $background;\n    border-left: 1px solid #CCC;\n    border-right: 1px solid #CCC;\n\n    /*height: 500px;\n    width: 320px;*/\n    height: 100%;\n    width: 100%;\n    /*margin: 2rem auto;*/\n    display: flex;\n    flex-direction: column;\n    font-family: 'helvetica', sans-serif;\n\n    .disconnected {\n        background: #FFFFCC;\n        padding: 0.25rem;\n    }\n    &.connected .disconnected {\n        display: none;\n    }\n    .offline {\n        display: none;\n    }\n    &.offline {\n\n      .disconnected {\n        display: none;\n      }\n      .offline {\n        background: #FF0000;\n        color: #FFF;\n        padding: 0.25rem;\n        display: block;\n      }\n    }\n\n    .powered_by {\n      flex-shrink: 0;\n      text-align: center;\n\n      border-bottom: 1px solid #CCC;\n      font-size: 14px;\n      padding: 0.25rem;\n      color: #666;\n\n      a {\n        text-decoration: none;\n        color: #666;\n      }\n\n      img {\n        position: relative;\n        top: 2px;\n      }\n    }\n\n   section {\n      flex-grow:  1;\n      flex-direction: column-reverse;\n      display: flex;\n      overflow-y: auto;\n\n     div div {\n        margin: 0.25rem;\n        clear: both;\n    }\n  }\n\n  footer {\n      border-top: 1px solid #CCC;\n      padding: 0.25rem;\n      input[type=\"text\"] {\n          flex-grow: 1;\n          font-size: 1.25rem;\n          outline: none;\n          border: none;\n      }\n      button {\n         width: 50px;\n         background: none;\n         border: 0;\n         cursor: pointer;\n         color: blue;\n         font-weight: bold;\n     }\n  }\n\n  form {\n      display: flex;\n      margin: 0;\n      padding: 0.25rem;\n  }\n\n  #message_template {\n      display: none;\n  }\n\n  .message {\n      font-size: 14px;\n      padding: 0.5rem;\n      background: $bot_message_background;\n      color: $bot_message_text;\n      border-radius: 5px;\n      width: auto;\n      display: inline-block;\n      max-width: 75%;\n\n  }\n\n  .file_attachment {\n\n    background: $bot_message_background;\n    color: $bot_message_text;\n    border-radius: 5px;\n    display: inline-block;\n    max-width: 75%;\n\n    img {\n      max-width: 100%;\n      display: block;\n    }\n\n  }\n\n    .button_message {\n      margin: 1rem 0;\n      border-radius: 4px;\n      border-color: $action_color;\n      border-style: solid;\n      color: $action_color;\n      border-width: 1px;\n      padding: 0.25rem 1rem;\n      text-decoration: none;\n      text-align: center;\n      box-shadow: 1px 1px 2px rgba(0,0,0,0.25);\n      display: block;\n    }\n\n\n  .message p {\n      margin-top: 0;\n      margin-bottom: 0.5rem;\n  }\n\n  .message p:last-child {\n      margin-bottom: 0;\n  }\n\n  .message.outgoing {\n      float: right;\n\n      background: $human_message_background;\n      color: $human_message_text;\n\n  }\n\n  #message_replies {\n      text-align: center;\n      overflow-x: auto;\n      flex-shrink: 0;\n      -webkit-overflow-scrolling: touch; /* Lets it scroll lazy */\n\n      ul {\n          list-style-type: none;\n          margin: 0px auto;\n          padding: 0;\n          li {\n              display: inline-block;\n              margin: 0.5rem;\n              margin-left: 0;\n          }\n      }\n\n      a {\n         text-decoration: none;\n         display: block;\n         border: 1px solid $botkit_purple;\n         color: $botkit_purple;\n         border-radius: 16px;\n         padding: 0.25rem 1rem;\n         font-size: 14px;\n         cursor: pointer;\n\n         &:hover {\n           background: $botkit_purple;\n           color: #FFF;\n         }\n     }\n   }\n}\n\n\n\n/* typing indicator CSS based on code by Joseph Fusco -> https://codepen.io/fusco/pen/XbpaYv */\n.typing-indicator {\n  display: table;\n  margin: 0 auto;\n  position: relative;\n  span {\n    height: 5px;\n    width: 5px;\n    float: left;\n    margin: 0 1px;\n    background-color: $bot_message_text;\n    display: block;\n    border-radius: 50%;\n    opacity: 0.4;\n    @for $i from 1 through 3 {\n      &:nth-of-type(#{$i}) {\n        animation: 1s blink infinite ($i * .3333s);\n      }\n    }\n  }\n}\n\n@keyframes blink {\n  50% {\n    opacity: 1;\n  }\n}\n"
  },
  {
    "path": "packages/generator-botkit/generators/web/templates/sass/_home.scss",
    "content": "#home {\n    @include clearfix;\n    position: relative;\n    max-width: 650px;\n    margin: auto;\n}\n\n#homepage_bot {\n    width: 400px;\n    height: 450px;\n    float: left;\n    border: 5px solid #333;\n\n    iframe {\n        border: 0;\n        height: 100%;\n        width: 100%;\n    }\n    box-shadow: 5px 5px 5px rgba(0,0,0,0.5);\n}\n\n#welcome {\n    margin-left: 440px;\n}\n"
  },
  {
    "path": "packages/generator-botkit/generators/web/templates/sass/embed.scss",
    "content": "$height: 400px;\n\n#embedded_messenger {\n\n  position: fixed;\n  z-index: 1000;\n\n  bottom: -$height;\n  right: 2rem;\n\n  height: $height + 34;\n  transition: 0.5s ease-in-out bottom;\n\n  &.active {\n    bottom: 0;\n  }\n\n  iframe {\n    height: $height;\n    width: 100%;\n    border: 0;\n  }\n\n  #message_header {\n    background: #000;\n    padding: 0.5rem 1rem;\n    color: #FFF;\n  }\n\n}\n"
  },
  {
    "path": "packages/generator-botkit/generators/web/templates/sass/styles.scss",
    "content": "/* shared botkit ui styles */\n@import \"_botkit\";\n\n/* chat client */\n@import \"_chat\";\n\n/* special styles for homepage */\n@import \"_home\";\n"
  },
  {
    "path": "packages/generator-botkit/generators/webex/index.js",
    "content": "/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\nvar Generator = require('yeoman-generator');\nvar _ = require('underscore');\n_.extend(Generator.prototype, require('yeoman-generator/lib/actions/install'));\n\nmodule.exports = class extends Generator {\n    async prompting() {\n\n        this.platform = await this.prompt([\n            {\n                type: \"input\",\n                name: \"access_token\",\n                message: \"Access Token\",\n            },\n            {\n                type: \"input\",\n                name: \"public_address\",\n                message: \"Public Address (in the form of https://<myhost.com/)\",\n            },\n        ]);\n\n    }\n\n    writing() {\n\n        this.fs.copy(\n            this.templatePath('features'),\n            this.destinationPath('features')\n        );\n\n        this.fs.copyTpl(\n            this.templatePath('.env'),\n            this.destinationPath('.env'),\n            { \n                platform: this.platform,\n                options: this.options,\n            },\n        );\n    }\n\n    install() {\n        this.npmInstall(['botbuilder-adapter-webex@latest']);\n    }\n\n};"
  },
  {
    "path": "packages/generator-botkit/generators/webex/templates/features/webex_features.js",
    "content": "/**\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nconst { BotkitConversation } = require('botkit');\n\nmodule.exports = function(controller) {\n\n    const NEW_ROOM_DIALOG = 'new_room_dialog';\n    const dialog = new BotkitConversation(NEW_ROOM_DIALOG, controller);\n    dialog.say('I created this room so we could continue our conversation in private...');\n    dialog.ask('How does that sound?', async(response, convo, bot) => {\n\n    }, {key: 'how_it_sounds'});\n    dialog.say('Ah, {{vars.how_it_sounds}}, eh?');\n    dialog.say('I guess that is that.')\n\n    controller.addDialog(dialog);\n\n    controller.hears('delete','message,direct_message', async(bot, message) => {\n\n        let reply = await bot.reply(message,'This message will be deleted in a few seconds.');\n        setTimeout(async () => {\n            let res = await bot.deleteMessage(reply);\n        }, 5000);\n\n    });\n\n\n    controller.hears('create a room','message,direct_message', async(bot, message) => {\n\n        // create a room\n        let room = await bot.api.rooms.create({title: 'botkit test room'});\n\n        // add user as member (bot is automatically added)\n        let membership2 = await bot.api.memberships.create({\n            roomId: room.id,\n            personId: message.user,\n        });\n\n        await bot.startConversationInRoom(room.id, message.user);\n        await bot.beginDialog(NEW_ROOM_DIALOG);\n\n    });\n\n    controller.on('memberships.created', async(bot, message) => {\n        console.log('memberships created', message);\n    });\n\n\n}"
  },
  {
    "path": "packages/generator-botkit/package.json",
    "content": "{\n  \"name\": \"generator-botkit\",\n  \"version\": \"4.15.0\",\n  \"description\": \"Automatically generate a Botkit application template for any supported platform\",\n  \"scripts\": {\n    \"pack\": \"npm pack\"\n  },\n  \"files\": [\n    \"generators\"\n  ],\n  \"keywords\": [\n    \"yeoman-generator\",\n    \"botkit\",\n    \"bots\",\n    \"chatbots\"\n  ],\n  \"author\": \"Microsoft Corp.\",\n  \"license\": \"MIT\",\n  \"homepage\": \"https://github.com/howdyai/botkit/blob/master/packages/generator-botkit#readme\",\n  \"bugs\": {\n    \"url\": \"https://github.com/howdyai/botkit/issues\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/howdyai/botkit.git\"\n  },\n  \"dependencies\": {\n    \"yeoman-generator\": \"5.6.1\",\n    \"underscore\": \"1.13.1\"\n  }\n}\n"
  },
  {
    "path": "packages/generator-botkit/readme.md",
    "content": "# generator-botkit\n**A [Yeoman](https://yeoman.io) template for generating [Botkit](https://npmjs.org/package/botkit) applications**\n\n## Get Started\n\nInstall Yeoman and this template:\n\n```bash\nnpm install -g yo generator-botkit\n```\n\nCreate a new folder for your project:\n\n```bash\nmkdir mybot\ncd mybot\n```\n\nFrom inside your project folder, generate the project:\n\n```bash\nyo botkit\n```\n\nThe generator will walk you through the process of configuring and installing your Botkit application. For each platform, a different set of API credentials and options will be collected.  [Platform specific provisioning guides can be found in the Botkit docs site &rarr;](https://github.com/howdyai/botkit/blob/main/packages/docs/provisioning/index.md)\n\nOnce the generator has completed its work, you will be left with a fully operational bot ready to be connected to the messaging platform.  To start the application, run `npm start`.  [Learn more about the anatomy of a Botkit application &rarr;](https://github.com/howdyai/botkit/blob/main/packages/docs/advanced.md#anatomy-of-a-botkit-app)\n\nThe entire process is shown below:\n\n![Botkit Yeoman generator in action](yeoman-generator.gif)\n\n## Community & Support\n\nJoin our thriving community of Botkit developers and bot enthusiasts at large.\nOver 10,000 members strong, [our Github site](https://github.com/howdyai/botkit) is\n_the place_ for people interested in the art and science of making bots.\nCome to ask questions, share your progress, and commune with your peers!\n\nYou can also find help from members of the Botkit team [in our dedicated Cisco Spark room](https://eurl.io/#SyNZuomKx)!\n\n## About Botkit\n\nBotkit is a part of the [Microsoft Bot Framework](https://dev.botframework.com).\n\nWant to contribute? [Read the contributor guide](https://github.com/howdyai/botkit/blob/master/CONTRIBUTING.md)\n\nBotkit is released under the [MIT Open Source license](https://github.com/howdyai/botkit/blob/master/LICENSE.md)"
  },
  {
    "path": "packages/testbot/.gitignore",
    "content": "node_modules/\n.DS_Store\n.vscode\n.env"
  },
  {
    "path": "packages/testbot/bot.js",
    "content": "const { Botkit } = require('botkit');\nconst { MongoDbStorage } = require('botbuilder-storage-mongodb');\nconst { BotkitCMSHelper } = require('botkit-plugin-cms');\n\nconst { SlackAdapter, SlackMessageTypeMiddleware, SlackIdentifyBotsMiddleware, SlackEventMiddleware } = require('botbuilder-adapter-slack');\n// const { WebexAdapter } = require('botbuilder-adapter-webex');\nconst { WebAdapter } = require('botbuilder-adapter-web');\n// const { FacebookAdapter, FacebookEventTypeMiddleware } = require('botbuilder-adapter-facebook');\n// const { HangoutsAdapter } = require('botbuilder-adapter-hangouts');\n// const { TwilioAdapter } = require('botbuilder-adapter-twilio-sms');\n\n\n// Load process.env values from .env file\nrequire('dotenv').config();\n\nlet storage = null;\nif (process.env.MONGO_URI) {\n    storage = mongoStorage = new MongoDbStorage({\n        url : process.env.MONGO_URI,\n        // database: \"botframework\",\n        // collection: \"botframework\"\n    });\n}\n\n/* ----------------------------------------------------------------------\n * .-.   .-.      .-.\n * : :.-.: :      : :\n * : :: :: : .--. : `-.  .--. .-.,-.\n * : `' `' ;' '_.'' .; :' '_.'`.  .'\n *  `.,`.,' `.__.'`.__.'`.__.':_,._;\n * Configure the Webex Teams adapter\n * ----------------------------------------------------------------------\n */\n// const adapter = new WebexAdapter({\n//     enable_incomplete: true,\n//     // access_token: process.env.WEBEX_ACCESS_TOKEN,\n//     // public_address: process.env.WEBEX_PUBLIC_ADDRESS,\n//     secret: 'random-secret-1234',\n// })\n\n/* ----------------------------------------------------------------------\n *  .--. .-.               .-.\n * : .--': :               : :.-.\n * `. `. : :   .--.   .--. : `'.'\n * _`, :: :_ ' .; ; '  ..': . `.\n * `.__.'`.__;`.__,_;`.__.':_;:_;\n * Configure the Slack adapter\n * ----------------------------------------------------------------------\n//  */\n// const adapter = new SlackAdapter({\n//     // enable_incomplete: true,\n//     verificationToken: process.env.verificationToken,\n//     clientSigningSecret: process.env.clientSigningSecret,  \n//     botToken: process.env.botToken,\n//     // clientId: process.env.clientId,\n//     // clientSecret: process.env.clientSecret,\n//     // scopes: ['bot'],\n//     // redirectUri: process.env.redirectUri,\n//     // getTokenForTeam: getTokenForTeam,\n//     // getBotUserByTeam: getBotUserByTeam,\n// });\n\n// let tokenCache = {};\n// let userCache = {};\n\n// if (process.env.TOKENS) {\n//     tokenCache = JSON.parse(process.env.TOKENS);\n// } \n\n// if (process.env.USERS) {\n//     userCache = JSON.parse(process.env.USERS);\n// } \n\n// async function getTokenForTeam(teamId) {\n//     if (tokenCache[teamId]) {\n//         return new Promise((resolve) => {\n//             setTimeout(function() {\n//                 resolve(tokenCache[teamId]);\n//             }, 150);\n//         });\n//     } else {\n//         console.error('Team not found in tokenCache: ', teamId);\n//     }\n// }\n\n// async function getBotUserByTeam(teamId) {\n//     if (userCache[teamId]) {\n//         return new Promise((resolve) => {\n//             setTimeout(function() {\n//                 resolve(userCache[teamId]);\n//             }, 150);\n//         });\n//     } else {\n//         console.error('Team not found in userCache: ', teamId);\n//     }\n// }\n\n\n// // Use SlackEventMiddleware to emit events that match their original Slack event types.\n// adapter.use(new SlackEventMiddleware());\n\n// // Use SlackMessageType middleware to further classify messages as direct_message, direct_mention, or mention\n// adapter.use(new SlackMessageTypeMiddleware());\n\n/* ----------------------------------------------------------------------\n *  __      __      ___.                        __           __   \n * /  \\    /  \\ ____\\_ |__   __________   ____ |  | __ _____/  |_ \n * \\   \\/\\/   // __ \\| __ \\ /  ___/  _ \\_/ ___\\|  |/ // __ \\   __\\\n *  \\        /\\  ___/| \\_\\ \\\\___ (  <_> )  \\___|    <\\  ___/|  |  \n *   \\__/\\  /  \\___  >___  /____  >____/ \\___  >__|_ \\\\___  >__|  \n *        \\/       \\/    \\/     \\/           \\/     \\/    \\/     \n * Configure the Websocket adapter\n * ----------------------------------------------------------------------\n */\nconst adapter = new WebAdapter({});\n\n// const adapter = new FacebookAdapter({\n//     // enable_incomplete: true,\n//     // verify_token: process.env.FACEBOOK_VERIFY_TOKEN,\n//     getAccessTokenForPage: async(team) => { console.log('GET TOKEN FOR TEAM', team); if (team === process.env.FACEBOOK_PAGE_ID) { return process.env.FACEBOOK_ACCESS_TOKEN } },\n//     app_secret: process.env.FACEBOOK_APP_SECRET,\n// })\n\n// // emit events based on the type of facebook event being received\n// adapter.use(new FacebookEventTypeMiddleware());\n\n\n// const adapter = new HangoutsAdapter({\n//     // enable_incomplete: true,\n//     token: process.env.GOOGLE_TOKEN,\n//     google_auth_params: {\n//         credentials: JSON.parse(process.env['GOOGLE_CREDS'])\n//     }\n// });\n\n// const adapter = new TwilioAdapter({\n//     // enable_incomplete: true,\n//     // twilio_number: process.env.TWILIO_NUMBER,\n//     // account_sid: process.env.TWILIO_ACCOUNT_SID,\n//     // auth_token: process.env.TWILIO_AUTH_TOKEN,\n// });\n\nconst controller = new Botkit({\n    debug: true,\n    webhook_uri: '/api/messages',\n    webserver_middlewares: [(req, res, next) => { console.log('REQ > ', req.url); next(); }],\n    // disable_console: true,\n    adapter: adapter,\n    // disable_webserver: true,\n    // adapterConfig: {\n    //     appId: process.env.APP_ID,\n    //     appPassword: process.env.APP_PASSWORD\n    // },\n    storage\n});\n\n// const cms = new BotkitCMSHelper({\n//     cms_uri: process.env.cms_uri,\n//     token: process.env.cms_token,\n// });\n\n// // add cms tools\n// controller.usePlugin(cms);\n\n// Once the bot has booted up its internal services, you can use them to do stuff.\ncontroller.ready(() => {\n\n    /* catch-all that uses the CMS to trigger dialogs */\n    if (controller.plugins.cms) {\n        controller.on('message,direct_message', async (bot, message) => {\n            let results = false;\n            results = await controller.plugins.cms.testTrigger(bot, message);\n\n            if (results !== false) {\n                // do not continue middleware!\n                return false;\n            }\n        });\n    }\n\n    // load traditional developer-created local custom feature modules\n    controller.loadModules(__dirname + '/features');\n\n    // load \"packaged\" plugins\n    // turn on verbose console logging of send/receive/web requests\n    // controller.usePlugin(require('./plugins/verbose/index.js'));\n\n    if (controller.webserver) {\n\n        controller.webserver.get('/', (req, res) => {\n            res.send(controller.version);\n        });\n\n\n        controller.webserver.get('/install', (req, res) => {\n            // getInstallLink points to slack's oauth endpoint and includes clientId and scopes\n            res.redirect(controller.adapter.getInstallLink());\n        });\n\n        controller.webserver.get('/install/auth', async (req, res) => {\n            try {\n                const results = await controller.adapter.validateOauthCode(req.query.code);\n\n                console.log('FULL OAUTH DETAILS', results);\n\n                // Store token by team in bot state.\n                tokenCache[results.team_id] = results.bot.bot_access_token;\n\n                // Capture team to bot id\n                // TODO: this will have to be customized\n                userCache[results.team_id] =  results.bot.bot_user_id;\n\n                res.json('Success! Bot installed.');\n\n            } catch (err) {\n                console.error('OAUTH ERROR:', err);\n                res.status(401);\n                res.send(err.message);\n            }\n        });\n    }\n});\n\n"
  },
  {
    "path": "packages/testbot/botframework.js",
    "content": "// const { FacebookAdapter } = require('botbuilder-adapter-facebook');\n// const { SlackAdapter, SlackMessageTypeMiddleware, SlackIdentifyBotsMiddleware, SlackEventMiddleware } = require('botbuilder-adapter-slack');\n// const { WebexAdapter } = require('botbuilder-adapter-webex');\n// const { HangoutsAdapter } = require('botbuilder-adapter-hangouts');\n// const { TwilioAdapter } = require('botbuilder-adapter-twilio-sms');\n\nconst { BotFrameworkAdapter } = require('botbuilder');\n\nconst restify = require('restify');\n\n// Load process.env values from .env file\nrequire('dotenv').config();\n\nconst adapter = new BotFrameworkAdapter({\n    appId: process.env.APP_ID,\n    appPassword: process.env.APP_SECRET\n})\n\n// const adapter = new FacebookAdapter({\n//     verify_token: process.env.FACEBOOK_VERIFY_TOKEN,\n//     app_secret: process.env.FACEBOOK_APP_SECRET,\n//     access_token: process.env.FACEBOOK_ACCESS_TOKEN\n// });\n\n// const adapter = new SlackAdapter({\n//     verificationToken: process.env.verificationToken,\n//     clientSigningSecret: process.env.clientSigningSecret,  \n//     botToken: process.env.botToken,\n// });\n\n// const adapter = new WebexAdapter({\n//     access_token: process.env.WEBEX_ACCESS_TOKEN,\n//     public_address: process.env.WEBEX_PUBLIC_ADDRESS,\n//     secret: 'random-secret-1234',\n// })\n\n// const adapter = new HangoutsAdapter({\n//     token: process.env.GOOGLE_TOKEN,\n//     google_auth_params: {\n//         credentials: JSON.parse(process.env['GOOGLE_CREDS'])\n//     }\n// });\n\n// const adapter = new TwilioAdapter({\n//     twilio_number: process.env.TWILIO_NUMBER,\n//     account_sid: process.env.TWILIO_ACCOUNT_SID,\n//     auth_token: process.env.TWILIO_AUTH_TOKEN,\n// });\n\n\nconst server = restify.createServer();\nserver.use(restify.plugins.bodyParser());\n\n// adapter.registerWebhookSubscription('/api/messages');\n\nserver.get('/api/messages', (req, res) => {\n    console.log('QUERY', req.query);\n\n    adapter.processActivity(req, res, async(context) => {\n        // do your bot logic here!\n\n\n        console.log('GOT INCOMING ACTIVITY', context.activity);\n        if (context.activity.type === 'message') {\n            await context.sendActivity('Received an message: ' + context.activity.text);\n        }\n\n        let api = await adapter.getAPI(context.activity);\n        let id = await api.callAPI('/me','GET', {});\n        console.log('ID FROM API', id);\n    });\n});\n\nserver.listen(3000);"
  },
  {
    "path": "packages/testbot/custom_express.js",
    "content": "/*\n\nThis file demonstrates how to use your own instance of Express\nalong with Botkit and one or more adapters.\n\nThis is also a good starting point for using multiple adapters.\n*/\nconst { Botkit } = require('botkit');\nconst http = require('http');\nconst express = require('express');\nconst bodyParser = require('body-parser');\n\n// Configure an Express app\nconst app = express();\n\n// Configure Botkit WITHOUT a webserver.\n// disable_webserver turns off the internal Express.\n// This means we need to configure our own webhook endpoint.\n// In this instance, we are configuring a Bot Framework adapter.\nconst controller = new Botkit({\n    disable_webserver: true,\n    adapterConfig: {\n        appId: process.env.APP_ID,\n        appPassword: process.env.APP_PASSWORD,\n    }\n});\n\n\n// some options for express\n// this setup is identical to the way Botkit configures itself\nconst _config =\n    {\n        jsonLimit: '100kb',\n        urlEncodedLimit: '100kb',\n        webhook_uri: '/api/messages',\n    };\n\n// capture raw body in addition to the parsed content\napp.use((req, res, next) => {\n    req.rawBody = '';\n    req.on('data', function(chunk) {\n        req.rawBody += chunk;\n    });\n    next();\n});\n\napp.use(bodyParser.json({ limit: _config.jsonLimit }));\napp.use(bodyParser.urlencoded({ limit: _config.urlEncodedLimit, extended: true }));\n\napp.post(_config.webhook_uri, (req, res) => {\n    // Allow the Botbuilder middleware to fire.\n    // this middleware is responsible for turning the incoming payload into a BotBuilder Activity\n    // which we can then use to turn into a BotkitMessage\n    controller.adapter.processActivity(req, res, controller.handleTurn.bind(controller)).catch((err) => {\n        console.error('Experienced an error inside the turn handler', err);\n        throw err;\n    });\n});\n\n// Define your bot handlers...\ncontroller.on('message', async(bot, message) => {\n    await bot.reply(message, 'Received.');\n})\n\n\n// fire up the webserver...\nconst server = http.createServer(app);\nserver.listen(process.env.port || process.env.PORT || 3000, () => {\n    console.log(`Webhook endpoint online:  http://localhost:${ process.env.PORT || 3000 }${ _config.webhook_uri }`);\n});\n"
  },
  {
    "path": "packages/testbot/features/bot_inspector_mode.js",
    "content": "/**\n* this module if installed into a botkit v4+ app will enable \"Bot Inspector\" mode in Bot Framework Emulator\n* This allows you to connect to the bot app running locally with emulator to inspect messages \n* as they come and go to the messaging platform.\n* Read more here:\n* https://github.com/Microsoft/botframework/blob/master/README.md#bot-inspector-new---preview\n*/\n// import botbuilder 4.4 library\nconst { InspectionMiddleware, InspectionState, BotFrameworkAdapter } = require('botbuilder');\n\nmodule.exports = function(controller) {\n\n    // Bot Framework inspection middleware allows you to debug from the emulator\n    let inspectionState = new InspectionState(controller.storage);\n    let inspector = new InspectionMiddleware(inspectionState, undefined, controller.conversationState);\n    controller.adapter.use(inspector);\n\n    controller.ready(function() {\n        // create an alternate adapter\n        const sidecar = new BotFrameworkAdapter();\n        // use the same middleware instance!\n        sidecar.use(inspector)\n        \n        // set up an alternate route for the emulator to connect to\n        console.log(`Use the Bot Framework Emulator in Inspect mode: http://localhost:${ process.env.PORT || 3000 }/api/sidecar`);\n        controller.webserver.post('/api/sidecar', (req, res) => {\n            sidecar.processActivity(req, res, async(turnContext) => {\n                // noop\n            });\n        });\n    });\n\n}"
  },
  {
    "path": "packages/testbot/features/botframework_features.js",
    "content": "const request = require('request');\n\nmodule.exports = function(controller) {\n\n    if (!controller.adapter.name) {\n\n        controller.hears('dm me', 'message', async(bot, message) => {\n            // this does not work with Bot Framework Emulator.\n            // to achieve the same thing, use bot.changeContext(message.reference);\n            await bot.startConversationWithUser(message.reference);\n            await bot.say('Hello! (in private)');\n        });\n\n        controller.hears('update me', 'message', async(bot, message) => {\n\n            let reply = await bot.reply(message,'reply');\n            await controller.adapter.updateActivity(bot.getConfig('context'), {\n                text: 'UPDATED!',\n                ...message.incoming_message,\n                ...reply\n            });\n\n        })\n\n\n        controller.hears('delete me', 'message', async(bot, message) => {\n\n            let reply = await bot.reply(message,'delete this!');\n\n            await controller.adapter.deleteActivity(bot.getConfig('context'), {\n                ...message.incoming_message,\n                activityId: reply.id\n            });\n\n        });\n\n        controller.hears('members', 'message', async(bot, message) => {\n\n            let members = await controller.adapter.getConversationMembers(bot.getConfig('context'));\n            await bot.reply(message,JSON.stringify(members));\n\n        });\n\n        controller.hears('conversations', 'message', async(bot, message) => {\n\n            let channels = await controller.adapter.getChannels(bot.getConfig('context'));\n            await bot.reply(message, JSON.stringify(channels));\n\n        });\n\n        controller.hears('card', 'message', async(bot, message) => {\n\n            await bot.reply(message,{\n                attachments: [{\n                    \"contentType\": \"application/vnd.microsoft.card.hero\",\n                    \"content\": {\n                        \"buttons\": [\n                            {\n                                \"type\": \"imBack\",\n                                \"title\": \"say hey\",\n                                \"value\": \"hey\"\n                            },\n                            {\n                                \"type\": \"imBack\",\n                                \"title\": \"say what up\",\n                                \"value\": \"what up\"\n                            },\n                            {\n                                \"type\": \"invoke\",\n                                \"title\": \"invoke\",\n                                \"value\": {command: 'alpha'}\n                            }\n                        ],\n                        \"subtitle\": \"subtitle is this\",\n                        \"text\": \"text of cards\",\n                        \"title\": \"this is the card\"\n                    }\n                }]\n            });\n\n        });\n\n        controller.on('invoke', async(bot, message) => {\n\n            // make sure to send back a special invoke response.\n            // depends on the type of invoke!\n            await bot.reply(message,{\n                type: 'invokeResponse',\n                value: {\n                    status: 200,\n                    body: {},\n                }\n            });\n\n            console.log('***************************************************************************');\n            console.log(JSON.stringify(message, null, 2));\n            console.log('***************************************************************************');\n            await bot.reply(message, 'Got it: ' + JSON.stringify(message.value));\n        });\n\n    }\n}"
  },
  {
    "path": "packages/testbot/features/convo.js",
    "content": "const { BotkitConversation } = require('botkit');\n\n\nmodule.exports = function(controller) {\n    const DIALOG_ID = 'welcome_dialog';\n    const welcome = new BotkitConversation(DIALOG_ID, controller);\n\n    welcome.say('Hey!');\n    welcome.ask({\n        text: ['Check this out...', 'YO! Check it.', 'HELLO HUME...'],\n        quick_replies: [\n            {\n                title: 'Foo',\n                payload: 'foo',\n            },\n            {\n                title: 'Bar',\n                payload: 'bar',\n            }\n        ],\n    },async(answer, convo, bot) => {\n        // noop.\n    },{key: 'waterfall_results'});\n\n    welcome.say('What is up??');\n    welcome.ask('what is your name', async (answer, convo, bot) => {\n        // noop\n        // answer contains the user's answer\n        // as does convo.vars.name\n    },{key: 'name'});\n\n    welcome.ask('Tell me something! I\\'ll hear it but won\\'t save the value.', async (answer, convo, bot) => {\n        // noop\n        // answer contains the user's answer\n        // answer can be used but is not persisted into the convo.vars\n    });\n\n    welcome.say('hrrm!');\n    welcome.say('ok, {{vars.name}}!');\n    welcome.ask('yes or no', [\n        {\n            pattern: 'yes',\n            handler: async function(answer, convo, bot) {\n                console.log('YES HANDLER');\n                console.log(convo);\n                return await convo.gotoThread('foo');\n            }\n        },\n        {\n            pattern: 'no',\n            handler: async function(answer, convo, bot) { \n                console.log(' NO HANDLER');\n                await convo.gotoThread('bar');\n            }\n        },\n        {\n            default: true,\n            handler: async (answer, convo, bot) => {\n                console.log('FALLBACK HANDLER');\n                await convo.repeat();\n                // do nothing\n            }\n        }\n    ], {key: 'answer'});\n\n    welcome.say('HUH WHAT DOES {{vars.answer}} MEAN?');\n\n    welcome.addMessage('YES!!! {{vars.foo}} {{vars.bar}}','foo');\n    welcome.addMessage('NOOOOOO', 'bar');\n\n    welcome.onChange('name', async(response, convo, bot) => {\n        // await bot.say('NO! NEVER!!!');\n        // await convo.gotoThread('bar')\n        await bot.say('You changed your name.');\n    });\n\n    welcome.before('foo', async(convo, bot) => {\n        // set a variable\n        convo.vars.foo = 'this was set in a before handler!';\n    });\n\n    welcome.before('bar', async(convo, bot) => {\n\n        // redirect the thread\n        convo.vars.bar = 'YOU HAVE BEEN REDIRECTED HERE.';\n\n        // you can send adhoc messages you want using bot.say\n        await bot.say('I refuse to accept that answer.');\n\n        await convo.gotoThread('foo');\n    });\n\n    welcome.after(async(results, bot) => {\n        // console.log('welcome completed', results);\n        // await bot.beginDialog('tacos');\n    });\n\n    // controller.cms.after('tacos', async(results, bot) => {\n    //     console.log('AFTER TACOS!!!!!!');\n    //     await bot.beginDialog('menu'); \n    // });\n\n    \n    controller.addDialog(welcome);\n\n    controller.afterDialog(welcome, async(bot, results) => {\n\n        console.log('WELCOME DIALOG HAS COMPLETED WITH RESULTS', results);\n        await bot.say('WELCOME SCRIPT COMPLETE, FULL RESULTS:\\n\\n```' + JSON.stringify(results,null,2) + '\\n```');\n\n    });\n\n    controller.hears(['welcome'],'message', async (bot, message) => {\n        await bot.beginDialog(DIALOG_ID, {});\n    });\n\n    controller.on('conversationUpdate', async(bot, message) => {\n        // check to see if this is the bot or another user.\n        var is_bot = message.incoming_message.membersAdded.filter((member) => {\n            return (member.id === message.incoming_message.recipient.id);\n        })\n        if (is_bot.length===0) {\n            await bot.beginDialog(DIALOG_ID);\n        }\n    });\n\n}"
  },
  {
    "path": "packages/testbot/features/convo_test.js",
    "content": "const { BotkitConversation } = require('botkit');\n\nmodule.exports = function(controller) {\n\n\n    // yes runs normally before it starts\n    // yes runs when using an action\n    // yes calls when looping itself\n    // yes runs when a handler is passed in as a function and inside it calls convo.gotothread\n    // runs when an onchange handler calls gotothread\n    // yes runs in an onbefore\n\n    let convo = new BotkitConversation('test_convo', controller);\n    controller.addDialog(convo);\n\n    convo.before('default', async(convo, bot) => {\n        await bot.say('BEFORE DEFAULT!');\n        convo.setVar('count', 0);\n    });\n\n    convo.say('This is the default thread.');\n    convo.addAction('second');\n\n    convo.before('second', async(convo, bot) => { \n        await bot.say('BEFORE SECOND');\n        convo.setVar('count', convo.vars.count + 1);\n        if (convo.vars.count > 2) {\n            await convo.gotoThread('third');\n        }\n    });\n    convo.addMessage('This is the second thread round {{vars.count}}', 'second');\n    convo.addAction('second','second');\n\n    convo.before('third', async(convo, bot) => {\n        await bot.say('BEFORE THIRD');\n    });\n\n    convo.addMessage('This is third','third');\n    convo.addQuestion('What do you think', async(response, convo, bot) => {\n        await convo.gotoThread('fourth');\n    }, 'think', 'third');\n\n    convo.before('fourth', async(convo, bot) => {\n        await bot.say('BEFORE FOURTH!!!');\n    });\n    convo.addMessage('this is the fourth thread', 'fourth');\n    convo.addQuestion('Will this work?', [], 'work', 'fourth');\n\n    convo.onChange('work', async(response, convo, bot) => {\n        await convo.gotoThread('fifth');\n    });\n\n    convo.before('fifth', async(convo, bot) => {\n        await bot.say('BEFORE FIFTH!!!');\n    });\n    convo.addMessage('this is the fifth thread','fifth');\n    convo.addAction('default', 'fifth');\n\n\n\n\n    controller.hears('convo_test', 'direct_message,message', async(bot, message) => { \n        await bot.beginDialog('test_convo');\n    });\n\n}"
  },
  {
    "path": "packages/testbot/features/dynamic_attachments.js",
    "content": "const { BotkitConversation } = require('botkit');\n\nmodule.exports = function(controller) {\n\n    let dialog = new BotkitConversation('dynamic_attachments', controller);   \n    dialog.ask({\n        text: 'What is your name?',\n        quick_replies: [\n            {\n                title: '{{vars.default_name}}',\n                payload: '{{vars.default_name}}',\n            }\n        ]\n    }, [], 'name');\n\n    dialog.ask({\n        text: 'Your name is:',\n        quick_replies: async(line, vars) => {\n            return [\n                {\n                    title: 'Foo',\n                    payload: 'foo',\n                },\n                {\n                    title: 'Bar',\n                    payload: 'bar',\n                },\n                {\n                    title: vars.name,\n                    payload: vars.name\n                }\n            ]\n        }\n    }, [], 'menu');\n\n    dialog.say({\n        text: 'Does this sound right?',\n        attachments: async(line, vars) => {\n            return [\n                {\n                    title: `Your name is ${vars.name} and you chose ${vars.menu}`\n                }\n            ];\n        }\n    });\n    controller.addDialog(dialog);\n\n    controller.hears('dynamic', 'message,direct_message,direct_mention', async(bot, message) => {\n        await bot.beginDialog('dynamic_attachments', {default_name: 'BEN'});\n    });\n\n}"
  },
  {
    "path": "packages/testbot/features/facebook_features.js",
    "content": "const { BotkitConversation } = require('botkit');\n\n\nmodule.exports = function(controller) {\n\n    if (controller.adapter.name === 'Facebook Adapter') {\n    /**\n     * Detect when a message has a sticker attached\n     */\n    controller.hears(async(message) => message.sticker_id, 'message', async(bot, message) => {\n        await bot.reply(message,'Cool sticker.');\n    });\n\n\n    controller.hears(new RegExp('quick'), 'message', async (bot, message) => {\n\n      await bot.reply(message,{\n          text: 'Here are some quick replies',\n          quick_replies: [\n              {\n                  title: 'Foo',\n                  payload: 'foo',\n              },\n              {\n                  title: 'Bar',\n                  payload: 'bar',\n              }\n          ]\n      });\n  });\n  \n    /**\n     * Detect a button click \n     */\n    controller.on('facebook_postback', async(bot, message) => {\n        await bot.reply(message,`I heard you posting back a post_back about ${ message.text }`);\n    });\n\n\n\n    let typing = new BotkitConversation('typing', controller);\n\n    typing.say('I am going to type for a while now...');\n    typing.addAction('typing');\n\n    // start the typing indicator\n    typing.addMessage({channelData: {sender_action: 'typing_on'}}, 'typing');\n    // trigger a gotoThread, which gives us an opportunity to delay the next message\n    typing.addAction('next_thread','typing');\n\n    typing.addMessage('typed!','next_thread');\n\n   // use the before handler to delay the next message \n    typing.before('next_thread',  async() => {\n        return new Promise((resolve, reject) => {\n            // simulate some long running process\n            setTimeout(resolve, 3000);\n        });\n    });\n\n    controller.addDialog(typing);\n\n    controller.hears('typing dialog', 'message', async(bot, message) => {\n        await bot.beginDialog('typing');\n    });\n\n    controller.hears('typing reply', 'message', async(bot, message) => {\n\n      await bot.reply(message,{sender_action: 'typing_on'});\n      setTimeout(async function() {\n        await bot.changeContext(message.reference);\n        await bot.reply(message,'typing done');\n      }, 3000);\n\n    });\n\n\n    controller.ready(async () => {\n        // example of proactive message\n        let bot = await controller.spawn(process.env.FACEBOOK_PAGE_ID);\n        bot.startConversationWithUser(process.env.FACEBOOK_ADMIN_USER).then(async () => {\n            let res = await bot.say('Hello human');\n            console.log('results of proactive message', res);\n        }); \n\n        let res = await bot.api.callAPI('/me/messenger_profile', 'delete', {fields: ['persistent_menu']});\n        console.log('results of delete menu', res);\n\n        res = await bot.api.callAPI('/me/messenger_profile', 'post', {\n            \"persistent_menu\":[\n              {\n                \"locale\":\"default\",\n                \"composer_input_disabled\": false,\n                \"call_to_actions\":[\n                  {\n                    \"title\":\"My Account\",\n                    \"type\":\"nested\",\n                    \"call_to_actions\":[\n                      {\n                        \"title\":\"Pay Bill\",\n                        \"type\":\"postback\",\n                        \"payload\":\"PAYBILL_PAYLOAD\"\n                      },\n                      {\n                        \"type\":\"web_url\",\n                        \"title\":\"Latest News\",\n                        \"url\":\"https://www.messenger.com/\",\n                        \"webview_height_ratio\":\"full\"\n                      }\n                    ]\n                  }\n                ]\n              }\n            ]\n          })\n          console.log('results of set menu', res);\n\n\n    });\n\n  }\n\n}"
  },
  {
    "path": "packages/testbot/features/flip_table.js",
    "content": "const request = require('request');\nmodule.exports = function(controller) {\n\n    controller.hears(['flip'], 'message', async (bot, message) => {\n        request.get('http://www.tableflipper.com/json', (e, r, json) => {\n            const url = JSON.parse(json);\n            bot.reply(message,url.gif);\n        });\n    });\n}"
  },
  {
    "path": "packages/testbot/features/get_reference.js",
    "content": "const { TurnContext } = require('botbuilder');\n\nmodule.exports = function(controller) {\n\n    controller.hears('reference','message', async(bot, message)=> {\n\n        const reference = TurnContext.getConversationReference(message.incoming_message);\n        await bot.reply(message, JSON.stringify(reference, null, 2));\n\n    });\n\n    controller.hears('thread me', 'message', async (bot, message) => {\n\n        await bot.startConversationInThread(message.channel, message.user, message.incoming_message.channelData.ts);\n        await bot.beginDialog('waterfall_sample');\n\n    });\n\n\n    controller.hears('thread it', 'message', async (bot, message) => {\n        await bot.replyInThread(message,'THREADED');\n    });\n\n    controller.hears('im me', 'message', async(bot, message) => {\n\n        await bot.startPrivateConversation(message.user);\n        await bot.beginDialog('waterfall_sample')\n\n    });\n\n\n    controller.hears('webex me', 'message', async(bot, message) => {\n        // switch to a 1:1\n        delete message.incoming_message.conversation;\n        const response = await bot.reply(message, '');\n        console.log('GOT REPLY RESPONSE', response);\n    });\n    controller.hears('\\<\\#.*?\\>', 'message', async(bot, message) => {\n\n        const channel = message.text.replace(/.*?\\<\\#(.*?)\\|.*?\\>.*/,\"$1\");\n\n        await bot.startConversationInChannel(channel, message.user);\n        await bot.beginDialog('waterfall_sample')\n\n    });\n\n    // async function foo() {\n    //     let bot = await controller.spawn();\n    //     await bot.startPrivateConversation('U024F7C89');\n    //     bot.say('I BOOTED');\n    // }\n\n    // foo();\n\n}"
  },
  {
    "path": "packages/testbot/features/hangouts_features.js",
    "content": "module.exports = function(controller) {\n\n    if (controller.adapter.name === 'Google Hangouts Adapter') {\n\n        controller.on('direct_message', async(bot, message) => {\n            await bot.reply(message,'I heard a private message');\n        });\n\n        controller.on('message', async(bot, message) => {\n            await bot.reply(message,'I heard a public message');\n        });\n\n        controller.on('bot_room_join', async(bot, message) => {\n            await bot.reply(message,'I just joined this room!');\n        });\n\n        controller.hears('thread dialog', ['message','direct_message'], async(bot, message) => {\n            await bot.startConversationInThread(message.channel, message.user);\n            await bot.beginDialog('waterfall_sample');\n        });\n\n        controller.hears('thread', ['message','direct_message'], async(bot, message) => {\n            await bot.replyInThread(message,'This is a new thread!');\n        });\n\n        controller.hears('update', ['message','direct_message'], async(bot, message) => {\n            const reply = await bot.reply(message,'This message will get updated in a few seconds.');\n            setTimeout(async function() {\n                await bot.updateMessage({\n                    text: '[ this message was update ]',\n                    id: reply.id\n                });\n            }, 3000);\n        });\n\n        controller.hears('delete', ['message','direct_message'], async(bot, message) => {\n            const reply = await bot.reply(message,'This message will get deleted in a few seconds.');\n            setTimeout(async function() {\n                await bot.deleteMessage(reply);\n                await bot.reply(message,'A message was deleted!');\n            }, 3000);\n        });\n\n\n        controller.hears('cards', ['message','direct_message'], async(bot, message) => {\n            bot.reply(message,{\n                cards: [\n                    {\n                        \"sections\": [\n                            {\n                                \"widgets\": [\n                                    {\n                                        \"image\": { \"imageUrl\": \"https://image.slidesharecdn.com/botkitsignal-160526164159/95/build-a-bot-with-botkit-1-638.jpg?cb=1464280993\" }\n                                    },\n                                    {\n                                        \"buttons\": [\n                                            {\n                                                \"textButton\": {\n                                                    \"text\": \"Open Link\",\n                                                    \"onClick\": {\n                                                        \"openLink\": {\n                                                            \"url\": \"https://botkit.ai/docs/\"\n                                                        }\n                                                    }\n                                                }\n                                            },\n                                            {\n                                                \"textButton\": {\n                                                    \"text\": \"Reply with New\",\n                                                    \"onClick\": {\n                                                        \"action\": {\n                                                            \"actionMethodName\": \"new\",\n                                                            \"parameters\": [\n                                                                {\n                                                                    \"key\":\"foo\",\n                                                                    \"value\": \"bar\"\n                                                                }\n                                                            ]\n                                                        }\n                                                    }\n                                                }\n                                            },\n                                            {\n                                                \"textButton\": {\n                                                    \"text\": \"Reply with Update\",\n                                                    \"onClick\": {\n                                                        \"action\": {\n                                                            \"actionMethodName\": \"update\",\n                                                            \"parameters\": [\n                                                                {\n                                                                    \"key\":\"foo\",\n                                                                    \"value\": \"bar\"\n                                                                }\n                                                            ]\n                                                        }\n                                                    }\n                                                }\n                                            }\n                                        ]\n                                    }\n                                ]\n                            }\n                        ]\n                    }\n                ]\n            })\n        });\n\n    }\n\n    controller.on('card_clicked', async(bot, message) => {\n\n        // send a sync reply\n        if (message.action.actionMethodName === 'new') {\n            await bot.replyWithNew(message, 'Card clicked, so I sent a new message.');\n        } else if (message.action.actionMethodName === 'update') {\n            await bot.replyWithUpdate(message, '[ This message was updated after a card click. ]');\n        }\n\n        // send a normal async reply\n        await bot.reply(message,'I got a click.');\n\n    });\n\n\n    controller.hears('proactive', ['message','direct_message'], async(bot, message) => {\n\n        // capture reference\n        const reference = message.reference;\n        await bot.reply(message,'I will pick this up in a little while...');\n\n        setTimeout(async function() {\n\n            const foo = await controller.spawn();\n            await foo.changeContext(reference);\n            await foo.say('OK I WAITED.');\n\n        }, 10000);\n\n    });\n        \n\n\n\n\n\n\n}"
  },
  {
    "path": "packages/testbot/features/hear_patterns.js",
    "content": "module.exports = function(controller) {\n\n    // use a function to match a condition in the message\n    controller.hears(async(message) => message.text && message.text.toLowerCase() === 'foo', ['message'], async (bot, message) => {\n        await bot.reply(message, 'I heard foo via a function test');\n    });\n\n    // use a regular expression to match the text of the message\n    controller.hears(new RegExp(/^\\d+$/), ['message','direct_message'], async function(bot, message) {\n        await bot.reply(message,{ text: 'I HEARD A NUMBER' });\n    });\n\n    // match any one of set of mixed patterns like a string, a regular expression\n    controller.hears(['allcaps', new RegExp(/^[A-Z\\s]+$/)], ['message','direct_message'], async function(bot, message) {\n        await bot.reply(message,{ text: 'I HEARD ALL CAPS' });\n    });\n\n}"
  },
  {
    "path": "packages/testbot/features/interruptions.js",
    "content": "const { BotkitConversation} = require('botkit');\n\nmodule.exports = function(controller) {\n\n    const dialog = new BotkitConversation('HELPDIALOG', controller);\n\n    dialog.ask('What can I help with?', [], 'subject');\n    dialog.say('HRRM! What do I know about {{vars.subject}}?');\n    dialog.addAction('display_results');\n\n    dialog.before('display_results', async(convo, bot) => {\n        convo.setVar('results', 'KNOWLEDGE BASE EMPTY');\n    });\n\n    dialog.addMessage('Here is what I know: {{vars.results}}', 'display_results');\n\n    controller.addDialog(dialog);\n\n    // hear the word help, and interrupt whatever is happening to handle it first.\n    controller.interrupts(async(message) => { return message.intent==='help' }, 'message', async(bot, message) => {\n        await bot.reply(message,'I heard you need help more than anything else!');\n        await bot.beginDialog('HELPDIALOG');\n    });\n\n\n    controller.interrupts(['quit','cancel'], 'message', async (bot, message) => {\n\n        await bot.reply(message,'LETS QUIT THIS JUNK!');\n        await bot.cancelAllDialogs();\n    });\n\n\n}"
  },
  {
    "path": "packages/testbot/features/looping_dialog.js",
    "content": "const { BotkitConversation } = require('botkit');\n\nmodule.exports = function(controller) {\n\n    let dialog = new BotkitConversation('looping', controller);\n\n    // define the questions in a variable\n    dialog.before('default', async(convo, bot) => {\n        // set list of questions\n        convo.setVar('questions', ['What is your name?','What is your quest?', 'What is the airspeed of an unladen swallow?']);\n        convo.setVar('question_index', 0);\n    });\n\n    // start off with an intro message\n    dialog.say('I have some questions for you...');\n    // start the loop\n    dialog.addAction('question-loop');\n\n    dialog.before('question-loop', async(convo, bot) => {\n\n        if (convo.vars.question_index < convo.vars.questions.length) {\n            convo.setVar('question', convo.vars.questions[convo.vars.question_index]);\n        } else {\n            await convo.gotoThread('end');\n        }\n\n    });\n\n    // use a variable for the question text:\n    dialog.addQuestion('{{vars.question}}', async(response, convo, bot) => {\n\n        // capture in answer_x\n        let key = 'answer_' + convo.vars.question_index;\n        convo.setVar(key, response);\n        convo.setVar('question_index', convo.vars.question_index + 1);\n\n    }, 'answer','question-loop');\n    dialog.addAction('question-loop', 'question-loop');\n\n    dialog.addMessage('ALL DONE!', 'end');\n\n    dialog.after(async(results, bot) => {\n         console.log('RESULTS OF LOOPING DIALOG', results);\n    });\n\n    controller.addDialog(dialog);\n\n    controller.hears('loop', 'message,direct_message', async(bot, message) => {\n        await bot.beginDialog('looping');\n    });\n\n\n}"
  },
  {
    "path": "packages/testbot/features/luis_recognizer.js",
    "content": "const { LuisRecognizer } = require('botbuilder-ai');\n\nmodule.exports = function(controller) {\n\n    if (process.env.LUIS_APPLICATIONID) {\n\n        const recognizer = new LuisRecognizer({\n            applicationId: process.env.LUIS_APPLICATIONID,\n            endpointKey: process.env.LUIS_ENDPOINTKEY,\n        });\n\n\n        controller.middleware.ingest.use(async (bot, message, next) => {\n            if (message.incoming_message.type === 'message') {\n                const results = await recognizer.recognize(message.context);\n                message.intent = LuisRecognizer.topIntent(results, 'None', process.env.LUIS_THRESHOLD || 0.7);\n                console.log('recognized',message.intent);\n            }\n\n            next();\n        });\n\n        controller.hears(async(message) => { return (message.intent && message.intent==='fart') }, 'message', async(bot, message) => {\n            bot.reply(message,':dash: ew')\n        });\n\n    }\n\n}"
  },
  {
    "path": "packages/testbot/features/middlewares.js",
    "content": "module.exports = function(controller) {\n\n    controller.middleware.receive.use((bot, message, next) => {\n        console.log('IN > ', message.text, message.type);\n        next();\n    });\n\n    controller.middleware.send.use((bot, message, next) => {\n        console.log('OUT > ', message.text, message.channelData && message.channelData.quick_replies ? message.channelData.quick_replies : null, message.channelData && message.channelData.attachments ? message.channelData.attachments : null);\n        next();\n    });\n\n    controller.middleware.ingest.use(async (bot, message, next) => {\n        message.touchedbyMiddleware = true;\n        next();\n    });\n\n}"
  },
  {
    "path": "packages/testbot/features/random_text_middleware.js",
    "content": "module.exports = function(controller) {\n\n\n    controller.middleware.send.use((bot, message, next) => {\n\n        if (Array.isArray(message.text)) {\n            message.text = message.text[Math.floor(Math.random() * message.text.length)];\n        }\n        next();\n\n    });\n\n    controller.hears('random','message', async(bot, message) => { \n\n            bot.reply(message,{\n                text: [\n                    'Random response 1',\n                    'Random response 2',\n                    'Random response 3'\n                ]\n            });\n\n    });\n\n}"
  },
  {
    "path": "packages/testbot/features/sample_onboarding.js",
    "content": "const { BotkitConversation } = require('botkit');\nconst { TextPrompt, WaterfallDialog } = require('botbuilder-dialogs');\n\n\nmodule.exports = function(controller) {\n\n    const ONBOARDING_PROMPT = 'onboarding_prompt';\n    const PROFILE_DIALOG = 'profile_dialog';\n    const ONBOARDING_DIALOG = 'onboarding_dialog';\n    const CONFIRM_DIALOG = 'confirm_dialog';\n    const START_OVER = 'start_over';\n\n    /**\n     * Create a TextPrompt that will be used by the profile dialog\n     */\n    const textPrompt = new TextPrompt(ONBOARDING_PROMPT);\n\n    /**\n     * Define a simple waterfall dialog that collects profile information.\n     */\n    const profile = new WaterfallDialog(PROFILE_DIALOG,[\n        async(step) => {\n            return await step.prompt(ONBOARDING_PROMPT, 'What is your name?');            \n        },\n        async(step) => {\n            // capture result of previous step\n            step.values.name = step.result;\n\n            return await step.prompt(ONBOARDING_PROMPT, 'What is your age?');\n        },\n        async(step) => {\n            // capture result of previous step\n            step.values.age = step.result;\n\n            return await step.prompt(ONBOARDING_PROMPT, 'What is your location?');\n        },\n        async(step) => {\n            // capture result of previous step\n            step.values.location = step.result;\n\n            return await step.endDialog(step.values);\n        }\n    ]);\n\n    const confirmation = new BotkitConversation(CONFIRM_DIALOG, controller);\n    confirmation.say('Your name is {{vars.profile.name}}, your age is {{vars.profile.age}} and your location is {{vars.profile.location}}');\n    confirmation.ask('Is that correct?', [\n        {\n            pattern: 'no',\n            handler: async(res, convo, bot) => {\n                await convo.gotoThread('try_again');\n                // convo\n            }\n        },\n        {\n            default: true,\n            handler: async(res, convo, bot) => {\n                // noop, just continue\n            }\n        }\n    ],{key:'confirmed'});\n    confirmation.say('All done!');\n    confirmation.addGotoDialog(START_OVER,'try_again');\n\n    const startover = new BotkitConversation(START_OVER, controller);\n    startover.say('Lets start from the top...');\n    startover.addChildDialog(PROFILE_DIALOG, 'profile');\n    startover.addGotoDialog(CONFIRM_DIALOG);\n\n    /**\n     * Now, define a BotkitConversation style dialog that will use the profile dialog as a child.\n     */\n    const onboarding = new BotkitConversation(ONBOARDING_DIALOG, controller);\n    onboarding.say('Hello, human! Nice to meet you.');\n    onboarding.say('Before we begin, I need to ask you some questions.');\n    onboarding.addChildDialog(PROFILE_DIALOG, 'profile');\n    onboarding.say('Thanks, {{vars.profile.name}}! Your onboarding has completed.');\n    onboarding.addGotoDialog(CONFIRM_DIALOG);\n\n    /**\n     * Add all of our dialogs to the bot.\n     */\n    controller.addDialog(textPrompt);\n    controller.addDialog(profile);\n    controller.addDialog(onboarding);\n    controller.addDialog(confirmation);\n    controller.addDialog(startover);\n\n    /** \n     * When the profile dialog ends, store the info!\n     */\n    controller.afterDialog(ONBOARDING_DIALOG, async(bot, results) => {\n\n        if (results.confirmed != 'no') {\n            console.log('PROFILE CAPTURED!', results);\n            // do something like store this in the database.\n        }\n    });\n\n    /**\n     * listen for someone to say \"onboarding\" and fire the parent dialog!\n     */\n    controller.hears('onboarding', 'message,direct_message', async(bot, message) => {\n        await bot.beginDialog(ONBOARDING_DIALOG);\n    })    \n\n}"
  },
  {
    "path": "packages/testbot/features/shutdown.js",
    "content": "module.exports = function(controller) {\n    controller.hears('shutdown', 'message', async(bot, message) => {\n        controller.shutdown();\n    });\n\n    controller.on('shutdown', async() => {\n        console.log('SHUTTING DOWN APP!');\n    });\n}"
  },
  {
    "path": "packages/testbot/features/slack_features.js",
    "content": "const { SlackDialog } = require('botbuilder-adapter-slack');\nconst { BotkitConversation } = require('botkit');\n\nmodule.exports = function(controller) {\n\n    if (controller.adapter.name === 'Slack Adapter') {\n        controller.ready(async () => {\n            if (process.env.MYTEAM) {\n                let bot = await controller.spawn(process.env.MYTEAM);\n                await bot.startConversationInChannel(process.env.MYCHAN,process.env.MYUSER);\n                bot.say('I AM AWOKEN.');\n            }\n        });\n\n        controller.on('reaction_added', async(bot, message) => {\n            await bot.reply(message,'Cool emoji');\n        });\n        \n        controller.on('member_joined_channel', async(bot, message) => {\n            await bot.reply(message, `Welcome hume!`);\n        });\n\n        controller.on('app_mention', async(bot, message) => {\n            await bot.reply(message, `Got an app_mention!`);\n        })\n\n        controller.hears('dm me', 'message', async(bot, message) => {\n            await bot.startPrivateConversation(message.user);\n            await bot.say(`Let's talk in private.`);\n        });\n\n\n        controller.on('direct_mention', async(bot, message) => {\n            await bot.reply(message, `I heard a direct mention that said \"${ message.text }\"`);\n        });\n\n        controller.on('mention', async(bot, message) => {\n            await bot.reply(message, `You mentioned me when you said \"${ message.text }\"`);\n        });\n\n        controller.hears('ephemeral', 'message,direct_message', async(bot, message) => {\n            await bot.replyEphemeral(message,'This is an ephemeral reply sent using bot.replyEphemeral()!');\n        });\n\n        controller.hears('threaded', 'message,direct_message', async(bot, message) => {\n            await bot.replyInThread(message,'This is a reply in a thread!');\n\n            await bot.startConversationInThread(message.channel, message.user, message.incoming_message.channelData.ts);\n            await bot.say('And this should also be in that thread!');\n        });\n\n        controller.hears('update', ['message','direct_message'], async(bot, message) => {\n            const reply = await bot.reply(message,'This message will get updated in a few seconds.');\n            setTimeout(async function() {\n                await bot.updateMessage({\n                    text: '[ this message was update ]',\n                    ...reply\n                });\n            }, 3000);\n        });\n\n        controller.hears('delete', ['message','direct_message'], async(bot, message) => {\n            return new Promise(async(resolve, reject) => {\n                console.log('SENDING DELETABLE MESSAGE');\n                const reply = await bot.reply(message,'This message will get deleted in a few seconds.');\n                setTimeout(async function() {\n                    await bot.deleteMessage(reply);\n                    await bot.reply(message,'A message was deleted!');\n                    resolve();\n                }, 100);\n            });\n        });\n\n\n        controller.hears('blocks', 'message', async(bot, message) => {\n\n            await bot.reply(message,{\n                blocks: [\n                    {\n                        \"type\": \"section\",\n                        \"text\": {\n                            \"type\": \"mrkdwn\",\n                            \"text\": \"Hello, Assistant to the Regional Manager Dwight! *Michael Scott* wants to know where you'd like to take the Paper Company investors to dinner tonight.\\n\\n *Please select a restaurant:*\"\n                        }\n                    },\n                    {\n                        \"type\": \"divider\"\n                    },\n                    {\n                        \"type\": \"section\",\n                        \"text\": {\n                            \"type\": \"mrkdwn\",\n                            \"text\": \"*Farmhouse Thai Cuisine*\\n:star::star::star::star: 1528 reviews\\n They do have some vegan options, like the roti and curry, plus they have a ton of salad stuff and noodles can be ordered without meat!! They have something for everyone here\"\n                        },\n                        \"accessory\": {\n                            \"type\": \"image\",\n                            \"image_url\": \"https://s3-media3.fl.yelpcdn.com/bphoto/c7ed05m9lC2EmA3Aruue7A/o.jpg\",\n                            \"alt_text\": \"alt text for image\"\n                        }\n                    },\n                    {\n                        \"type\": \"section\",\n                        \"text\": {\n                            \"type\": \"mrkdwn\",\n                            \"text\": \"*Kin Khao*\\n:star::star::star::star: 1638 reviews\\n The sticky rice also goes wonderfully with the caramelized pork belly, which is absolutely melt-in-your-mouth and so soft.\"\n                        },\n                        \"accessory\": {\n                            \"type\": \"image\",\n                            \"image_url\": \"https://s3-media2.fl.yelpcdn.com/bphoto/korel-1YjNtFtJlMTaC26A/o.jpg\",\n                            \"alt_text\": \"alt text for image\"\n                        }\n                    },\n                    {\n                        \"type\": \"section\",\n                        \"text\": {\n                            \"type\": \"mrkdwn\",\n                            \"text\": \"*Ler Ros*\\n:star::star::star::star: 2082 reviews\\n I would really recommend the  Yum Koh Moo Yang - Spicy lime dressing and roasted quick marinated pork shoulder, basil leaves, chili & rice powder.\"\n                        },\n                        \"accessory\": {\n                            \"type\": \"image\",\n                            \"image_url\": \"https://s3-media2.fl.yelpcdn.com/bphoto/DawwNigKJ2ckPeDeDM7jAg/o.jpg\",\n                            \"alt_text\": \"alt text for image\"\n                        }\n                    },\n                    {\n                        \"type\": \"divider\"\n                    },\n                    {\n                        \"type\": \"actions\",\n                        \"elements\": [\n                            {\n                                \"type\": \"button\",\n                                \"text\": {\n                                    \"type\": \"plain_text\",\n                                    \"text\": \"Farmhouse\",\n                                    \"emoji\": true\n                                },\n                                \"value\": \"Farmhouse\"\n                            },\n                            {\n                                \"type\": \"button\",\n                                \"text\": {\n                                    \"type\": \"plain_text\",\n                                    \"text\": \"Kin Khao\",\n                                    \"emoji\": true\n                                },\n                                \"value\": \"Kin Khao\"\n                            },\n                            {\n                                \"type\": \"button\",\n                                \"text\": {\n                                    \"type\": \"plain_text\",\n                                    \"text\": \"Ler Ros\",\n                                    \"emoji\": true\n                                },\n                                \"value\": \"Ler Ros\"\n                            }\n                        ]\n                    }\n                ]\n            });\n\n        });\n\n        controller.on('block_actions', async (bot, message) => {\n            await bot.reply(message, `Sounds like your choice is ${ message.incoming_message.channelData.actions[0].value }`)\n        });\n\n        controller.on('slash_command', async(bot, message) => {\n            if (message.text === 'plain') {\n                await bot.reply(message, 'This is a plain reply');\n            } else if (message.text === 'public') {\n                await bot.replyPublic(message, 'This is a public reply');\n            } else if (message.text === 'private') {\n                await bot.replyPrivate(message, 'This is a private reply');\n            }\n\n            // set http status\n            bot.httpBody({text:'You can send an immediate response using bot.httpBody()'});\n\n        });\n\n        controller.on('interactive_message', async (bot, message) => {\n\n            console.log('INTERACTIVE MESSAGE', message);\n\n            switch(message.actions[0].name) {\n                case 'replace':\n                    await bot.replyInteractive(message,'[ A previous message was successfully replaced with this less exciting one. ]');\n                    break;\n                case 'dialog':\n                    await bot.replyWithDialog(message, new SlackDialog('this is a dialog', '123', 'Submit', [\n                        {\n                            type: 'text',\n                            label: 'Field 1',\n                            name: 'field1',\n                        },\n                        {\n                            type: 'text',\n                            label: 'Field 2',\n                            name: 'field2',\n                        }\n                    ]).notifyOnCancel(true).state('foo').asObject());\n                    break;\n                default:\n                    await bot.reply(message, 'Got a button click!');\n            }\n        });\n\n\n        controller.on('dialog_submission', async (bot, message) => {\n            await bot.reply(message, 'Got a dialog submission');\n\n            // Return an error to Slack\n            bot.dialogError([\n                {\n                    \"name\": \"field1\",\n                    \"error\": \"there was an error in field1\"\n                }\n            ])\n        });\n\n        controller.on('dialog_cancellation', async (bot, message) => {\n            await bot.reply(message, 'Got a dialog cancellation');\n        });\n\n\n        const dialog = new BotkitConversation('slack_buttons', controller);\n\n        dialog.ask({\n            text: 'Click one of these ATTACHMENT BUTTONS',\n            attachments: [\n                {\n                    title: 'This is an attachment',\n                    text: 'It has some buttons',\n                    callback_id: '123',\n                    actions: [\n                        {\n                            name: 'buttona',\n                            type:  'button',\n                            text: 'Click this',\n                            value: 'Clicked this',                                \n                        },\n                        {\n                            name: 'buttonb',\n                            type:  'button',\n                            text: 'Click that',\n                            value: 'Clicked that',                                \n                        }\n                    ]\n                }\n            ]\n        }, [], 'button');\n\n        dialog.say('You clicked {{vars.button}}');\n\n        dialog.ask({\n            text: 'Click one of these BLOCK BUTTONS',\n            blocks: [\n                {\n                    \"type\": \"actions\",\n                    \"elements\": [\n                        {\n                            \"type\": \"button\",\n                            \"text\": {\n                                \"type\": \"plain_text\",\n                                \"text\": \"BLOCK A\",\n                                \"emoji\": true\n                            },\n                            \"value\": \"A\"\n                        },\n                        {\n                            \"type\": \"button\",\n                            \"text\": {\n                                \"type\": \"plain_text\",\n                                \"text\": \"BLOCK B\",\n                                \"emoji\": true\n                            },\n                            \"value\": \"B\"\n                        },\n                        {\n                            \"type\": \"button\",\n                            \"text\": {\n                                \"type\": \"plain_text\",\n                                \"text\": \"BLOCK C\",\n                                \"emoji\": true\n                            },\n                            \"value\": \"C\"\n                        }\n                    ]\n                }\n            ]\n        }, [], 'block');\n\n        dialog.say('You clicked {{vars.block}}');\n        controller.addDialog(dialog);\n\n        controller.hears('buttons', 'message,direct_message,direct_mention', async(bot, message) => {\n            await bot.beginDialog('slack_buttons');\n        });\n\n    }\n\n}"
  },
  {
    "path": "packages/testbot/features/slack_modals.js",
    "content": "module.exports = function(controller) {\n\n    if (controller.adapter.name === 'Slack Adapter') {\n\n        controller.hears('modal','direct_message,direct_mention,mention', async(bot, message) => {\n\n            const responseCard = {\n              attachments: [\n                {\n                  text: 'Click the button to launch a modal.',\n                  actions: [\n                    {\n                      name: 'modal',\n                      type: 'button',\n                      text: 'Open Modal',\n                      value: 'modal',\n                    }\n                  ],\n                  callback_id: 'modal',\n                }\n              ]\n            };\n\n            await bot.reply(message, responseCard);\n\n        });\n\n        controller.on('interactive_message', async(bot, message) => {\n          if (message.actions[0].name === 'modal') {\n              const trigger_id = message.trigger_id;\n              const response = await bot.api.views.open({\n                trigger_id: trigger_id,\n                view: {\n                  \"type\": \"modal\",\n                  \"callback_id\": \"modal-identifier\",\n                  \"title\": {\n                    \"type\": \"plain_text\",\n                    \"text\": \"Just a modal\"\n                  },\n                  \"blocks\": [\n                    {\n                      \"type\": \"section\",\n                      \"block_id\": \"section-identifier\",\n                      \"text\": {\n                        \"type\": \"mrkdwn\",\n                        \"text\": \"This is a sample modal\"\n                      },\n                      \"accessory\": {\n                        \"type\": \"button\",\n                        \"text\": {\n                          \"type\": \"plain_text\",\n                          \"text\": \"Update this modal\",\n                        },\n                        \"value\": \"update_modal\",\n                        \"action_id\": \"button-identifier\",\n                      }\n                    },\n                  ]\n                }\n              });\n          }\n        });\n\n        controller.hears('update_modal','block_actions', async(bot, message) => {\n\n          const response = await bot.api.views.update({\n            view_id: message.container.view_id,\n            view: {\n              \"type\": \"modal\",\n              \"callback_id\": \"modal-identifier\",\n              \"title\": {\n                \"type\": \"plain_text\",\n                \"text\": \"Just a modal\"\n              },\n              \"blocks\": [\n                {\n                  \"type\": \"section\",\n                  \"block_id\": \"section-identifier\",\n                  \"text\": {\n                    \"type\": \"mrkdwn\",\n                    \"text\": \"This is a sample modal\"\n                  }\n                },\n                {\n                  \"type\": \"input\",\n                  \"block_id\": \"ticket-title\",\n                  \"label\": {\n                    \"type\": \"plain_text\",\n                    \"text\": \"Ticket title\"\n                  },\n                  \"element\": {\n                    \"type\": \"plain_text_input\",\n                    \"action_id\": \"ticket-title-value\"\n                  }\n                },\n                {\n                  \"type\": \"input\",\n                  \"block_id\": \"ticket-desc\",\n                  \"label\": {\n                    \"type\": \"plain_text\",\n                    \"text\": \"Ticket description\"\n                  },\n                  \"element\": {\n                    \"type\": \"plain_text_input\",\n                    \"multiline\": true,\n                    \"action_id\": \"ticket-desc-value\"\n                  }\n                }\n              ],\n              \"submit\": {\n                \"type\": \"plain_text\",\n                \"text\": \"Submit\"\n              }\n            }\n          });\n\n        });\n\n\n        controller.on('view_submission', async(bot, message) => {\n          console.log('VIEW SUBMISSION', message.view.state.values);\n          bot.httpBody({\n            response_action: 'errors',\n            errors: {\n              \"ticket-desc\": 'I will never accept a value, you are doomed!'\n            }\n          })\n\n        })\n\n    }\n}\n\n"
  },
  {
    "path": "packages/testbot/features/teams_features.js",
    "content": "const { TeamsInvokeMiddleware } = require('botkit');\n\nmodule.exports = function(controller) {\n\n    if (!controller.adapter.name) {\n\n      controller.adapter.use(new TeamsInvokeMiddleware());\n\n      const adaptiveCard = {\n        \"type\": \"AdaptiveCard\",\n        \"body\": [\n            {\n                \"type\": \"TextBlock\",\n                \"text\": \"Here is a ninja cat:\"\n            },\n            {\n                \"type\": \"Image\",\n                \"url\": \"http://adaptivecards.io/content/cats/1.png\",\n                \"size\": \"Medium\"\n            },\n            {\n              \"type\": \"ActionSet\",\n              \"actions\": [\n                  {\n                      \"type\": \"Action.Submit\",\n                      \"title\": \"Message Submit\",\n                      \"id\": \"begin\",\n                      \"data\": {\n                          \"command\": \"message\"\n                      }\n                  },\n                  {\n                    \"type\": \"Action.Submit\",\n                    \"title\": \"Card Submit\",\n                    \"id\": \"begin\",\n                    \"data\": {\n                        \"command\": \"card\"\n                    }\n                  },\n                  {\n                    \"type\": \"Action.Submit\",\n                    \"title\": \"Close\",\n                    \"id\": \"begin\",\n                    \"data\": {\n                        \"command\": \"close\"\n                    }\n                },\n              ],\n              \"horizontalAlignment\": \"Center\"\n          }\n        ],\n        \"version\": \"1.0\"\n    }\n\n        controller.hears('getTeamDetails', 'message', async(bot, message) => {\n          try {\n            await bot.reply(message, JSON.stringify(await bot.teams.getTeamDetails(bot.getConfig('context'))));\n          } catch(err) {\n            await bot.reply(message, err.message);\n          }\n        });\n\n        controller.hears('getTeamChannels', 'message', async(bot, message) => {\n          try {\n            await bot.reply(message, JSON.stringify(await bot.teams.getTeamChannels(bot.getConfig('context'))));\n          } catch(err) {\n            await bot.reply(message, err.message);\n          }\n        });\n\n\n        controller.hears('getMember', 'message', async(bot, message) => {\n          try {\n            await bot.reply(message, JSON.stringify(await bot.teams.getMember(bot.getConfig('context'), message.user)));\n          } catch(err) {\n            await bot.reply(message, err.message);\n          }\n        });\n\n        controller.hears('taskModule', 'message', async(bot, message) => {\n          await bot.reply(message,{\n            attachments: [{\n                \"contentType\": \"application/vnd.microsoft.card.hero\",\n                \"content\": {\n                    \"buttons\": [\n                        {\n                            \"type\": \"invoke\",\n                            \"title\": \"Task Module\",\n                            \"value\": {type: 'task/fetch'}\n                        }\n                    ],\n                    \"text\": \"Launch a task module by clicking the button.\",\n                    \"title\": \"INVOKE A TASK MODULE!\"\n                }\n            }]\n        });\n      });\n\n      controller.on('task/fetch', async(bot, message) => {\n        await bot.replyWithTaskInfo(message,{\n              \"type\": \"continue\",\n              \"value\": {\n                \"title\": \"Task module title\",\n                \"height\": 500,\n                \"width\": \"medium\",\n                card: {\n                  contentType: 'application/vnd.microsoft.card.adaptive',\n                  content: adaptiveCard,\n                }\n              }\n          })\n      });\n\n\n    controller.on('task/submit', async(bot, message) => {\n\n        if (message.value.data.command == 'message') {\n          // reply with a message\n          await bot.replyWithTaskInfo(message, {\n              type: 'message',\n              value: 'Submitted!',\n          });\n        } else if (message.value.data.command == 'card') {\n            // reply with another card\n          await bot.replyWithTaskInfo(message, {\n              \"type\": \"continue\",\n              \"value\": {\n                \"title\": \"Task module title\",\n                \"height\": 500,\n                \"width\": \"medium\",\n                card: {\n                  contentType: 'application/vnd.microsoft.card.adaptive',\n                  content: adaptiveCard,\n                }\n              }\n          });\n        } else {\n            // just close the task module\n            await bot.replyWithTaskInfo(message, null);\n        }\n\n      });\n\n    }\n}"
  },
  {
    "path": "packages/testbot/features/test_convo.js",
    "content": "module.exports = function(controller) {\n    // controller.cms.before('tests','default', async function (bot, convo) {\n    //     convo.vars.bar = 'foo';\n    //     convo.vars.foo = 'bar';\n\n    //     await bot.say('A');\n    // });\n\n    // controller.cms.before('tests','default', async function (bot, convo) {\n    //     convo.vars.handler1 = true;\n    //     convo.gotoThread('new thread');\n\n    //     await bot.say('B');\n\n    // });\n\n    // controller.cms.before('tests','new thread', async function (bot, convo) {\n    //     convo.vars.handler2 = 'true';\n    //     convo.gotoThread('new thread 2');\n\n    //     await bot.say('C');\n\n    // });\n\n    // controller.cms.onChange('tests', 'question_1', async function (bot, convo, value) {\n    //     console.log('CHANGED QUESTION_1 VALUE', value);\n    //     convo.vars.question_1 = 'OVERRIDDEN';\n    //     convo.gotoThread('final');\n\n    //     await bot.say('D');\n\n    // });\n\n    // controller.cms.after('tests', async function (bot, results) {\n    //     // make sure all vars are set\n    //     if (!(results.bar && results.foo && results.handler1 && results.handler2)) {\n    //         throw new Error('FAILED TO AGGREGATE VARS THROUGH STEPS');\n    //     }\n    //     console.log('TESTS SCRIPT IS DONE!', results);\n\n    //     await bot.say('E');\n\n    // });\n\n}"
  },
  {
    "path": "packages/testbot/features/twilio_features.js",
    "content": "const Twilio = require('twilio');\n\nmodule.exports = function(controller) {\n\n    if (controller.adapter.name === 'Twilio SMS Adapter') {\n        controller.on('picture_message', async(bot, message) => {\n            bot.reply(message, 'Nice pic!');\n        });\n\n        controller.hears('twiml','message', async(bot, message) => {\n\n            let twiml = new Twilio.twiml.MessagingResponse();\n            twiml.message('This is a message sent using the HTTP response and TWIML');\n            bot.httpBody(twiml.toString());\n            \n        });\n    }\n}"
  },
  {
    "path": "packages/testbot/features/typescript.ts",
    "content": "import { Botkit } from 'botkit';\nimport { SlackBotWorker } from 'botbuilder-slack';\n\nmodule.exports = function(controller: Botkit) {\n\n    controller.on('direct_message', async(bot: SlackBotWorker, message: any): Promise<boolean> => {\n\n        // intellisene!\n        bot.reply(message, { text: 'foo' });\n\n        // stop processing this message once received here.\n        return false;\n    });\n\n\n}"
  },
  {
    "path": "packages/testbot/features/waterfall_dialog.js",
    "content": "/* This is a sample feature module that uses Bot Builder Waterfall dialogs */\n\nconst { WaterfallDialog, TextPrompt } = require('botbuilder-dialogs');\n\nconst DIALOG_ID = 'waterfall_sample';\nconst PROMPT_ID = 'waterfall_prompt';\nconst sample_waterfall = new WaterfallDialog(DIALOG_ID, [\n\n    async (step) => {\n        await step.context.sendActivity('This is the first step of a waterfall dialog');\n        return await step.next();\n    },\n    async (step) => {\n        return await step.prompt(PROMPT_ID,'Say something! I will receive your input.');\n    },\n    async (step) => {\n        const result = step.result;\n        step.values.something = result;\n        await step.context.sendActivity('You said ' + result);\n        return await step.next();\n    },\n    async (step) => {\n        await step.context.sendActivity('Done');\n        return await step.endDialog(step.values);\n    }\n]);\n\nmodule.exports = function(controller) {\n\n    controller.addDialog(new TextPrompt(PROMPT_ID));\n    controller.addDialog(sample_waterfall);\n\n    controller.afterDialog(sample_waterfall, async(bot, results) => {\n\n        console.log('WATERFALL DIALOG HAS COMPLETED WITH RESULTS', results);\n\n    });\n\n    controller.hears(['waterfall'], 'message, direct_message', async(bot) => {\n        await bot.beginDialog(DIALOG_ID, {});\n    });\n\n}"
  },
  {
    "path": "packages/testbot/features/webex_features.js",
    "content": "const { BotkitConversation } = require('botkit');\n\nmodule.exports = function(controller) {\n\n    if (controller.adapter.name == 'Webex Adapter') {\n\n      controller.ready(async function() {\n        await controller.adapter.registerAdaptiveCardWebhookSubscription('/api/messages');\n      });\n\n    const NEW_ROOM_DIALOG = 'new_room_dialog';\n    const dialog = new BotkitConversation(NEW_ROOM_DIALOG, controller);\n    dialog.say('I created this room so we could continue our conversation in private...');\n    dialog.ask('How does that sound?', async(response, convo, bot) => {\n\n    }, {key: 'how_it_sounds'});\n    dialog.say('Ah, {{vars.how_it_sounds}}, eh?');\n    dialog.say('I guess that is that.')\n\n    controller.addDialog(dialog);\n\n    controller.hears('delete','message,direct_message', async(bot, message) => {\n\n        let reply = await bot.reply(message,'This message will be deleted in a few seconds.');\n        setTimeout(async () => {\n            let res = await bot.deleteMessage(reply);\n        }, 5000);\n\n    });\n\n    controller.hears('adaptive_card','message,direct_message', async(bot, message) => {\n        let card = {\n            \"$schema\": \"http://adaptivecards.io/schemas/adaptive-card.json\",\n        \"type\": \"AdaptiveCard\",\n        \"version\": \"1.0\",\n        \"body\": [\n          {\n            \"type\": \"ColumnSet\",\n            \"columns\": [\n              {\n                \"type\": \"Column\",\n                \"width\": 2,\n                \"items\": [\n                  {\n                    \"type\": \"TextBlock\",\n                    \"text\": \"Tell us about yourself\",\n                    \"weight\": \"bolder\",\n                    \"size\": \"medium\"\n                  },\n                  {\n                    \"type\": \"TextBlock\",\n                    \"text\": \"We just need a few more details to get you booked for the trip of a lifetime!\",\n                    \"isSubtle\": true,\n                    \"wrap\": true\n                  },\n                  {\n                    \"type\": \"TextBlock\",\n                    \"text\": \"Don't worry, we'll never share or sell your information.\",\n                    \"isSubtle\": true,\n                    \"wrap\": true,\n                    \"size\": \"small\"\n                  },\n                  {\n                    \"type\": \"TextBlock\",\n                    \"text\": \"Your name\",\n                    \"wrap\": true\n                  },\n                  {\n                    \"type\": \"Input.Text\",\n                    \"id\": \"Name\",\n                    \"placeholder\": \"John Andersen\"\n                  },\n                  {\n                    \"type\": \"TextBlock\",\n                    \"text\": \"Your website\",\n                    \"wrap\": true\n                  },\n                  {\n                    \"type\": \"Input.Text\",\n                    \"id\" : \"Url\",\n                    \"placeholder\": \"https://example.com\"\n                  },\n                  {\n                    \"type\": \"TextBlock\",\n                    \"text\": \"Your email\",\n                    \"wrap\": true\n                  },\n                  {\n                    \"type\": \"Input.Text\",\n                    \"id\": \"Email\",\n                    \"placeholder\": \"john.andersen@example.com\",\n                    \"style\": \"email\"\n                  },\n                  {\n                    \"type\": \"TextBlock\",\n                    \"text\": \"Phone Number\"\n                  },\n                  {\n                    \"type\": \"Input.Text\",\n                    \"id\": \"Tel\",\n                    \"placeholder\": \"+1 408 526 7209\",\n                    \"style\": \"tel\"\n                  }\n                ]\n              },\n              {\n                \"type\": \"Column\",\n                \"width\": 1,\n                \"items\": [\n                  {\n                    \"type\": \"Image\",\n                    \"url\": \"https://upload.wikimedia.org/wikipedia/commons/b/b2/Diver_Silhouette%2C_Great_Barrier_Reef.jpg\",\n                    \"size\": \"auto\"\n                  }\n                ]\n              }\n            ]\n          }\n        ],\n        \"actions\": [\n          {\n            \"type\": \"Action.Submit\",\n            \"title\": \"Submit\"\n          }\n        ]\n      };\n\n          await bot.reply(message, {\n              text: 'here is a card',\n              attachments: [{\n                  content: card,\n                  \"contentType\": \"application/vnd.microsoft.card.adaptive\",\n                }],\n          });\n    })\n\n    controller.on('attachmentActions', async(bot, message) => {\n      console.log('GOT A CARD SUBMIT', message);\n    });\n    \n    controller.hears('threaded', 'message,direct_message', async(bot, message) => {\n      \n      let text = 'I\\'m responding to you in a thread!';\n      await bot.replyInThread(message, {markdown: text});\n\n\n      // message.parentId ? message.parentId : message.id\n      //  if the message is in the main channel, respond in a thread\n      //  if the message is already in a thread, respond to the same thread\n      await bot.startConversationInThread(message.channel, message.user, (message.parentId ? message.parentId : message.id));\n      await bot.say('And this should also be in that thread!');\n    });\n\n    controller.hears('create a room','message,direct_message', async(bot, message) => {\n\n        // create a room\n        let room = await bot.api.rooms.create({title: 'botkit test room'});\n\n        // add user as member (bot is automatically added)\n        let membership2 = await bot.api.memberships.create({\n            roomId: room.id,\n            personId: message.user,\n        });\n\n        await bot.startConversationInRoom(room.id, message.user);\n        await bot.beginDialog(NEW_ROOM_DIALOG);\n\n    });\n\n    controller.on('memberships.created', async(bot, message) => {\n        console.log('memberships created', message);\n    });\n\n    controller.hears('orgId', 'message, direct_message', async(bot, message) => {\n        await bot.reply(message, 'Your org id is ' + message.orgId);\n    });\n\n    controller.on('direct_message', async(bot, message) => {\n        await bot.reply(message, 'I heard a DM on webex');\n    });\n\n  }\n\n}"
  },
  {
    "path": "packages/testbot/features/websocket_features.js",
    "content": "const { BotkitConversation } = require('botkit');\n\nmodule.exports = function(controller) {\n\n    if (controller.adapter.name === 'Web Adapter') {\n\n        console.log('Loading sample Websocket features...');\n\n        controller.publicFolder('/',__dirname  + '/../public');\n\n        /**\n         * Send a message to new users / people with no user id cookie set\n         */\n        controller.on('hello', async(bot, message) => {\n            await bot.reply(message,'Nice to meet you, human!');\n        });\n\n        /**\n         * Send a message to returning users\n         */\n        controller.on('welcome_back', async(bot, message) => {\n            await bot.reply(message,'Welcome back, human.');\n        });\n\n\n        /** \n         * demo the use of the quick reply feature\n         */\n        controller.hears(new RegExp('quick'), 'message', async (bot, message) => {\n\n\n            await bot.reply(message,{\n                text: 'Here are some quick replies',\n                quick_replies: [\n                    {\n                        title: 'Foo',\n                        payload: 'foo',\n                    },\n                    {\n                        title: 'Bar',\n                        payload: 'bar',\n                    }\n                ]\n            });\n        });\n\n        let typing = new BotkitConversation('typing', controller);\n\n        typing.say('I am going to type for a while now...');\n        typing.addAction('typing');\n    \n        // start the typing indicator\n        typing.addMessage({type: 'typing'}, 'typing');\n        // trigger a gotoThread, which gives us an opportunity to delay the next message\n        typing.addAction('next_thread','typing');\n    \n        typing.addMessage('typed!','next_thread');\n    \n       // use the before handler to delay the next message \n        typing.before('next_thread',  async() => {\n            return new Promise((resolve, reject) => {\n                // simulate some long running process\n                setTimeout(resolve, 3000);\n            });\n        });\n    \n        controller.addDialog(typing);\n    \n        controller.hears('typing dialog', 'message', async(bot, message) => {\n            await bot.beginDialog('typing');\n        });\n\n        controller.hears('typing reply', 'message', async(bot, message) => {\n\n            await bot.reply(message, {type: 'typing'});\n    \n            setTimeout(async () => {\n                // will have to reset context because turn has now ended.\n                await bot.changeContext(message.reference);\n                await bot.reply(message, 'Typed!');\n            }, 1000);\n    \n        });\n\n        let replies = new BotkitConversation('replies', controller);\n        replies.ask({\n            text: 'Click one of these suggestions!',\n            quick_replies: [\n                {\n                    title: 'Foo',\n                    payload: 'foo',\n                },\n                {\n                    title: 'Bar',\n                    payload: 'bar',\n                }\n            ]\n        }, [], 'reply');\n        replies.say('You clicked {{vars.reply}}');\n        replies.ask({\n            text: 'Click one of these suggestions!',\n            quick_replies: [\n                {\n                    title: 'Norm',\n                    payload: 'norm',\n                },\n                {\n                    title: 'Flarm',\n                    payload: 'flarm',\n                }\n            ]\n        }, async(response, convo, bot, message) => {\n            console.log('GOT REPLY', response);\n            console.log('FULL PAyLOAD',message);\n        }, 'reply');\n        replies.say('You clicked {{vars.reply}}');\n\n        controller.addDialog(replies);\n\n        controller.hears('qqq', 'message', async(bot, message) => {\n            await bot.beginDialog('replies');\n        });\n\n\n\n\n\n    }\n\n}"
  },
  {
    "path": "packages/testbot/features/z_fallback.js",
    "content": "const { BotkitConversation } = require('botkit');\nmodule.exports = function(controller) {\n\n    controller.on('message', async (bot, message) => {\n        await bot.reply(message, { text: 'Echo: ' + message.text});\n    });\n}"
  },
  {
    "path": "packages/testbot/multiadapter.js",
    "content": "/**\n * This is a sample implementation of a multi-adapter bot\n * This demonstrates using the built-in Bot Framework adapter along side the Botkti webchat AND Facebook adapters.\n */\n\nconst { Botkit } = require('botkit');\n\nconst { WebAdapter } = require('botbuilder-adapter-web');\nconst { FacebookAdapter, FacebookEventTypeMiddleware } = require('botbuilder-adapter-facebook');\n\n// Load process.env values from .env file\nrequire('dotenv').config();\n\n\n// set up Web Adapter\nconst web_adapter = new WebAdapter({});\n\n// Set up Facebook Adapter\nconst facebook_adapter = new FacebookAdapter({\n    enable_incomplete: true,\n    verify_token: process.env.FACEBOOK_VERIFY_TOKEN,\n    access_token: process.env.FACEBOOK_ACCESS_TOKEN,\n    app_secret: process.env.FACEBOOK_APP_SECRET,\n    app_id: process.env.FACEBOOK_APP_ID,\n})\n\n// emit events based on the type of facebook event being received\nfacebook_adapter.use(new FacebookEventTypeMiddleware());\n\n\n// boot controller with the built-in bot framework adapter that works with emulator and Azure bot service\n// you could also pass in one of the above adapters as the \"default\" adapter and bind secondary as below...\nconst controller = new Botkit({\n    debug: true,\n    webhook_uri: '/api/messages',\n    webserver_middlewares: [(req, res, next) => { console.log('REQ > ', req.url); next(); }],\n});\n\ncontroller.ready(() => {\n\n    // Make the web chat work \n    // make the web chat available at http://localhost:3000\n    controller.publicFolder('/',__dirname  + '/public');\n    // bind websocket to the webserver\n    web_adapter.createSocketServer(controller.http, {}, controller.handleTurn.bind(controller));\n\n\n    // Make the Facebook adapter work\n    // we do this by creating a SECOND webhook endpoint\n    // and calling the facebook_adapter directly as below.\n    // this is what Botkit does internally, see:\n    // https://github.com/howdyai/botkit/blob/master/packages/botkit/src/core.ts#L675\n    controller.webserver.post('/api/facebook', (req, res) => {\n        facebook_adapter.processActivity(req, res, controller.handleTurn.bind(controller)).catch((err) => {\n            console.error('Experienced an error inside the turn handler', err);\n            throw err;\n        });\n    });\n\n    controller.on('message', async (bot, message) => {\n        const adapter_type = bot.getConfig('context').adapter.name;\n        await bot.reply(message,`I heard ya on my ${ adapter_type }  adapter`);\n    });\n\n});"
  },
  {
    "path": "packages/testbot/package.json",
    "content": "{\n  \"name\": \"testbot\",\n  \"version\": \"1.0.0\",\n  \"description\": \"a test harness for testing in-progress changes to botkit\",\n  \"main\": \"bot.js\",\n  \"scripts\": {\n    \"start\": \"node bot.js\"\n  },\n  \"author\": \"benbrown@gmail.com\",\n  \"license\": \"MIT\",\n  \"dependencies\": {\n    \"botbuilder\": \"^4.15.0\",\n    \"botbuilder-ai\": \"^4.15.0\",\n    \"botbuilder-dialogs\": \"^4.15.0\",\n    \"botbuilder-adapter-facebook\": \"^1.0.0\",\n    \"botbuilder-adapter-hangouts\": \"^1.0.0\",\n    \"botbuilder-adapter-slack\": \"^1.0.0\",\n    \"botbuilder-adapter-twilio-sms\": \"^1.0.0\",\n    \"botbuilder-adapter-web\": \"^1.0.0\",\n    \"botbuilder-adapter-webex\": \"^1.0.0\",\n    \"botbuilder-dialogs-botkit-cms\": \"0.0.1\",\n    \"botbuilder-storage-mongodb\": \"^0.9.5\",\n    \"botkit\": \"^4.15.0\",\n    \"botkit-plugin-cms\": \"^1.0.3\",\n    \"dotenv\": \"^6.2.0\",\n    \"express-basic-auth\": \"^1.1.6\",\n    \"restify\": \"^8.4.0\"\n  }\n}\n"
  },
  {
    "path": "packages/testbot/plugins/verbose/index.js",
    "content": "module.exports = function(botkit) {\n\n    return {\n        name: 'Verbose Console Logger',\n        init: function(botkit) {\n            // Log requests to console using an Express middleware\n            if (botkit.webserver) {\n                botkit.webserver.use(function(req, res, next) {\n                    console.log('> ', req.url);\n                    next();\n                });\n            }\n\n        },\n        middlewares: {\n            receive: [\n                function(bot, message, next) {\n                    console.log(`RCVD > ${ message.type } >`, message.text);\n                    next();\n                }\n            ],\n            send: [\n                function(bot, message, next) {\n                    console.log('SENT > ', message.text);\n                    next();\n                }\n            ]\n        }\n    }\n}"
  },
  {
    "path": "packages/testbot/plugins/verbose/public/test.txt",
    "content": "this is a test!!! DOT TEXT."
  },
  {
    "path": "packages/testbot/plugins/verbose/views/layout.hbs",
    "content": "<head>\n    <title>TEST</title>\n</head>\n<body>\n\n<header>header</header>\n{{body}}\n<footer>footer</footer>\n</body>\n"
  },
  {
    "path": "packages/testbot/plugins/verbose/views/template.hbs",
    "content": "<h1>this is the homepage tempalte</h1>>"
  },
  {
    "path": "packages/testbot/public/client.js",
    "content": "var converter = new showdown.Converter();\nconverter.setOption('openLinksInNewWindow', true);\n\nvar Botkit = {\n    config: {\n        ws_url: (location.protocol === 'https:' ? 'wss' : 'ws') + '://' + location.host,\n        reconnect_timeout: 3000,\n        max_reconnect: 5,\n        enable_history: false,\n    },\n    options: {\n        use_sockets: true,\n    },\n    reconnect_count: 0,\n    guid: null,\n    current_user: null,\n    on: function (event, handler) {\n        this.message_window.addEventListener(event, function (evt) {\n            handler(evt.detail);\n        });\n    },\n    trigger: function (event, details) {\n        var event = new CustomEvent(event, {\n            detail: details\n        });\n        this.message_window.dispatchEvent(event);\n    },\n    request: function (url, body) {\n        var that = this;\n        return new Promise(function (resolve, reject) {\n            var xmlhttp = new XMLHttpRequest();\n\n            xmlhttp.onreadystatechange = function () {\n                if (xmlhttp.readyState == XMLHttpRequest.DONE) {\n                    if (xmlhttp.status == 200) {\n                        var response = xmlhttp.responseText;\n                        var message = null;\n                        try {\n                            message = JSON.parse(response);\n                        } catch (err) {\n                            reject(err);\n                            return;\n                        }\n                        resolve(message);\n                    } else {\n                        reject(new Error('status_' + xmlhttp.status));\n                    }\n                }\n            };\n\n            xmlhttp.open(\"POST\", url, true);\n            xmlhttp.setRequestHeader(\"Content-Type\", \"application/json\");\n            xmlhttp.send(JSON.stringify(body));\n        });\n\n    },\n    send: function (text, e) {\n        var that = this;\n        if (e) e.preventDefault();\n        if (!text) {\n            return;\n        }\n        var message = {\n            type: 'outgoing',\n            text: text\n        };\n\n        this.clearReplies();\n        that.renderMessage(message);\n\n        that.deliverMessage({\n            type: 'message',\n            text: text,\n            user: this.guid,\n            channel: this.options.use_sockets ? 'websocket' : 'webhook'\n        });\n\n        this.input.value = '';\n\n        this.trigger('sent', message);\n\n        return false;\n    },\n    deliverMessage: function (message) {\n        if (this.options.use_sockets) {\n            this.socket.send(JSON.stringify(message));\n        } else {\n            this.webhook(message);\n        }\n    },\n    getHistory: function (guid) {\n        var that = this;\n        if (that.guid) {\n            that.request('/botkit/history', {\n                user: that.guid\n            }).then(function (history) {\n                if (history.success) {\n                    that.trigger('history_loaded', history.history);\n                } else {\n                    that.trigger('history_error', new Error(history.error));\n                }\n            }).catch(function (err) {\n                that.trigger('history_error', err);\n            });\n        }\n    },\n    webhook: function (message) {\n        var that = this;\n\n        that.request('/api/messages', message).then(function (messages) {\n            messages.forEach((message) => {\n                that.trigger(message.type, message);\n            });\n        }).catch(function (err) {\n            that.trigger('webhook_error', err);\n        });\n\n    },\n    connect: function (user) {\n\n        var that = this;\n\n        if (user && user.id) {\n            Botkit.setCookie('botkit_guid', user.id, 1);\n\n            user.timezone_offset = new Date().getTimezoneOffset();\n            that.current_user = user;\n            console.log('CONNECT WITH USER', user);\n        }\n\n        // connect to the chat server!\n        if (that.options.use_sockets) {\n            that.connectWebsocket(that.config.ws_url);\n        } else {\n            that.connectWebhook();\n        }\n\n    },\n    connectWebhook: function () {\n        var that = this;\n        if (Botkit.getCookie('botkit_guid')) {\n            that.guid = Botkit.getCookie('botkit_guid');\n            connectEvent = 'welcome_back';\n        } else {\n            that.guid = that.generate_guid();\n            Botkit.setCookie('botkit_guid', that.guid, 1);\n        }\n\n        if (this.options.enable_history) {\n            that.getHistory();\n        }\n\n        // connect immediately\n        that.trigger('connected', {});\n        that.webhook({\n            type: connectEvent,\n            user: that.guid,\n            channel: 'webhook',\n        });\n\n    },\n    connectWebsocket: function (ws_url) {\n        var that = this;\n        // Create WebSocket connection.\n        that.socket = new WebSocket(ws_url);\n\n        var connectEvent = 'hello';\n        if (Botkit.getCookie('botkit_guid')) {\n            that.guid = Botkit.getCookie('botkit_guid');\n            connectEvent = 'welcome_back';\n        } else {\n            that.guid = that.generate_guid();\n            Botkit.setCookie('botkit_guid', that.guid, 1);\n        }\n\n        if (this.options.enable_history) {\n            that.getHistory();\n        }\n\n        // Connection opened\n        that.socket.addEventListener('open', function (event) {\n            console.log('CONNECTED TO SOCKET');\n            that.reconnect_count = 0;\n            that.trigger('connected', event);\n            that.deliverMessage({\n                type: connectEvent,\n                user: that.guid,\n                channel: 'socket',\n                user_profile: that.current_user ? that.current_user : null,\n            });\n        });\n\n        that.socket.addEventListener('error', function (event) {\n            console.error('ERROR', event);\n        });\n\n        that.socket.addEventListener('close', function (event) {\n            console.log('SOCKET CLOSED!');\n            that.trigger('disconnected', event);\n            if (that.reconnect_count < that.config.max_reconnect) {\n                setTimeout(function () {\n                    console.log('RECONNECTING ATTEMPT ', ++that.reconnect_count);\n                    that.connectWebsocket(that.config.ws_url);\n                }, that.config.reconnect_timeout);\n            } else {\n                that.message_window.className = 'offline';\n            }\n        });\n\n        // Listen for messages\n        that.socket.addEventListener('message', function (event) {\n            var message = null;\n            try {\n                message = JSON.parse(event.data);\n            } catch (err) {\n                that.trigger('socket_error', err);\n                return;\n            }\n\n            that.trigger(message.type, message);\n        });\n    },\n    clearReplies: function () {\n        this.replies.innerHTML = '';\n    },\n    quickReply: function (payload) {\n        this.send(payload);\n    },\n    focus: function () {\n        this.input.focus();\n    },\n    renderMessage: function (message) {\n        var that = this;\n        if (!that.next_line) {\n            that.next_line = document.createElement('div');\n            that.message_list.appendChild(that.next_line);\n        }\n        if (message.text) {\n            message.html = converter.makeHtml(message.text);\n        }\n\n        that.next_line.innerHTML = that.message_template({\n            message: message\n        });\n        if (!message.isTyping) {\n            delete (that.next_line);\n        }\n    },\n    triggerScript: function (script, thread) {\n        this.deliverMessage({\n            type: 'trigger',\n            user: this.guid,\n            channel: 'socket',\n            script: script,\n            thread: thread\n        });\n    },\n    identifyUser: function (user) {\n\n        user.timezone_offset = new Date().getTimezoneOffset();\n\n        this.guid = user.id;\n        Botkit.setCookie('botkit_guid', user.id, 1);\n\n        this.current_user = user;\n\n        this.deliverMessage({\n            type: 'identify',\n            user: this.guid,\n            channel: 'socket',\n            user_profile: user,\n        });\n    },\n    receiveCommand: function (event) {\n        switch (event.data.name) {\n            case 'trigger':\n                // tell Botkit to trigger a specific script/thread\n                console.log('TRIGGER', event.data.script, event.data.thread);\n                Botkit.triggerScript(event.data.script, event.data.thread);\n                break;\n            case 'identify':\n                // link this account info to this user\n                console.log('IDENTIFY', event.data.user);\n                Botkit.identifyUser(event.data.user);\n                break;\n            case 'connect':\n                // link this account info to this user\n                Botkit.connect(event.data.user);\n                break;\n            default:\n                console.log('UNKNOWN COMMAND', event.data);\n        }\n    },\n    sendEvent: function (event) {\n\n        if (this.parent_window) {\n            this.parent_window.postMessage(event, '*');\n        }\n\n    },\n    setCookie: function (cname, cvalue, exdays) {\n        var d = new Date();\n        d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));\n        var expires = \"expires=\" + d.toUTCString();\n        document.cookie = cname + \"=\" + cvalue + \";\" + expires + \";path=/\";\n    },\n    getCookie: function (cname) {\n        var name = cname + \"=\";\n        var decodedCookie = decodeURIComponent(document.cookie);\n        var ca = decodedCookie.split(';');\n        for (var i = 0; i < ca.length; i++) {\n            var c = ca[i];\n            while (c.charAt(0) == ' ') {\n                c = c.substring(1);\n            }\n            if (c.indexOf(name) == 0) {\n                return c.substring(name.length, c.length);\n            }\n        }\n        return \"\";\n    },\n    generate_guid: function () {\n        function s4() {\n            return Math.floor((1 + Math.random()) * 0x10000)\n                .toString(16)\n                .substring(1);\n        }\n        return s4() + s4() + '-' + s4() + '-' + s4() + '-' +\n            s4() + '-' + s4() + s4() + s4();\n    },\n    boot: function (user) {\n\n        console.log('Booting up');\n\n        var that = this;\n\n\n        that.message_window = document.getElementById(\"message_window\");\n\n        that.message_list = document.getElementById(\"message_list\");\n\n        var source = document.getElementById('message_template').innerHTML;\n        that.message_template = Handlebars.compile(source);\n\n        that.replies = document.getElementById('message_replies');\n\n        that.input = document.getElementById('messenger_input');\n\n        that.focus();\n\n        that.on('connected', function () {\n            that.message_window.className = 'connected';\n            that.input.disabled = false;\n            that.sendEvent({\n                name: 'connected'\n            });\n        })\n\n        that.on('disconnected', function () {\n            that.message_window.className = 'disconnected';\n            that.input.disabled = true;\n        });\n\n        that.on('webhook_error', function (err) {\n\n            alert('Error sending message!');\n            console.error('Webhook Error', err);\n\n        });\n\n        that.on('typing', function () {\n            that.clearReplies();\n            that.renderMessage({\n                isTyping: true\n            });\n        });\n\n        that.on('sent', function () {\n            // do something after sending\n        });\n\n        that.on('message', function (message) {\n\n            console.log('RECEIVED MESSAGE', message);\n            that.renderMessage(message);\n\n        });\n\n        that.on('message', function (message) {\n            if (message.goto_link) {\n                window.location = message.goto_link;\n            }\n        });\n\n\n        that.on('message', function (message) {\n            that.clearReplies();\n            if (message.quick_replies) {\n\n                var list = document.createElement('ul');\n\n                var elements = [];\n                for (var r = 0; r < message.quick_replies.length; r++) {\n                    (function (reply) {\n\n                        var li = document.createElement('li');\n                        var el = document.createElement('a');\n                        el.innerHTML = reply.title;\n                        el.href = '#';\n\n                        el.onclick = function () {\n                            that.quickReply(reply.payload);\n                        }\n\n                        li.appendChild(el);\n                        list.appendChild(li);\n                        elements.push(li);\n\n                    })(message.quick_replies[r]);\n                }\n\n                that.replies.appendChild(list);\n\n                // uncomment this code if you want your quick replies to scroll horizontally instead of stacking\n                // var width = 0;\n                // // resize this element so it will scroll horizontally\n                // for (var e = 0; e < elements.length; e++) {\n                //     width = width + elements[e].offsetWidth + 18;\n                // }\n                // list.style.width = width + 'px';\n\n                if (message.disable_input) {\n                    that.input.disabled = true;\n                } else {\n                    that.input.disabled = false;\n                }\n            } else {\n                that.input.disabled = false;\n            }\n        });\n\n        that.on('history_loaded', function (history) {\n            if (history) {\n                for (var m = 0; m < history.length; m++) {\n                    that.renderMessage({\n                        text: history[m].text,\n                        type: history[m].type == 'message_received' ? 'outgoing' : 'incoming', // set appropriate CSS class\n                    });\n                }\n            }\n        });\n\n\n        if (window.self !== window.top) {\n            // this is embedded in an iframe.\n            // send a message to the master frame to tell it that the chat client is ready\n            // do NOT automatically connect... rather wait for the connect command.\n            that.parent_window = window.parent;\n            window.addEventListener(\"message\", that.receiveCommand, false);\n            that.sendEvent({\n                type: 'event',\n                name: 'booted'\n            });\n            console.log('Messenger booted in embedded mode');\n\n        } else {\n\n            console.log('Messenger booted in stand-alone mode');\n            // this is a stand-alone client. connect immediately.\n            that.connect(user);\n        }\n\n        return that;\n    }\n};\n\n\n(function () {\n    // your page initialization code here\n    // the DOM will be available here\n    Botkit.boot();\n})();"
  },
  {
    "path": "packages/testbot/public/css/embed.css",
    "content": "#embedded_messenger {\n  position: fixed;\n  z-index: 1000;\n  bottom: -400px;\n  right: 2rem;\n  height: 434px;\n  transition: 0.5s ease-in-out bottom;\n}\n#embedded_messenger.active {\n  bottom: 0;\n}\n#embedded_messenger iframe {\n  height: 400px;\n  width: 100%;\n  border: 0;\n}\n#embedded_messenger #message_header {\n  background: #000;\n  padding: 0.5rem 1rem;\n  color: #FFF;\n}\n\n/*# sourceMappingURL=embed.css.map */\n"
  },
  {
    "path": "packages/testbot/public/css/styles.css",
    "content": "/* shared botkit ui styles */\n* {\n  box-sizing: border-box;\n}\n\nbody,\nhtml {\n  margin: 0;\n  padding: 0;\n  font-size: 18px;\n  background-color: #FFF;\n  font-family: \"helvetica\", sans-serif;\n}\n\n.wrapper {\n  position: relative;\n  max-width: 1000px;\n  margin: 0 auto;\n}\n.wrapper:after {\n  content: \"\";\n  display: table;\n  clear: both;\n}\n\n.box {\n  border: 2px solid #CCC;\n  padding: 1rem calc(1rem - 2px);\n  margin-bottom: 1rem;\n}\n.box:after {\n  content: \"\";\n  display: table;\n  clear: both;\n}\n.box h1,\n.box h2,\n.box h3 {\n  margin-top: 0;\n}\n\nfooter {\n  text-align: center;\n}\n\n.hero {\n  text-align: center;\n  padding: 2rem;\n}\n.hero h1 {\n  font-size: 4rem;\n  margin: 0;\n}\n\na {\n  color: #a795ef;\n}\n\n.copyurl {\n  width: 100%;\n  font-size: 1.25rem;\n}\n\ndiv.input label {\n  font-weight: bold;\n  font-size: smaller;\n}\n\n.addon {\n  display: flex;\n  border: 1px solid #999;\n  border-radius: 6px;\n  padding: 5px;\n  background: #F0F0F0;\n}\n.addon input,\n.addon textarea {\n  flex-grow: 1;\n  border: 0;\n  background: transparent;\n}\n.addon button {\n  flex-grow: 0;\n  background: transparent;\n  border: 1px solid #999;\n  border-radius: 6px;\n  font-weight: bold;\n}\n.addon button.textarea {\n  align-self: flex-start;\n  padding: 0.5rem;\n}\n.addon button:hover {\n  background: #FFF;\n  color: #a795ef;\n}\n\ndiv.hr {\n  border: 1px dashed #ccc;\n  width: 10%;\n  margin: 4rem auto;\n  height: 1px;\n}\n\na.button {\n  border: 2px solid #a795ef;\n  font-weight: bold;\n  margin: 0;\n  border-radius: 3px;\n  display: inline-block;\n  padding: 0.5rem 2rem;\n  text-align: center;\n  text-decoration: none;\n  box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.2);\n  background-color: #FFF;\n  transition: box-shadow 0.1s linear;\n}\na.button:hover {\n  box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.1);\n}\n\n/* chat client */\n#message_window {\n  background: #FFFFFF;\n  border-left: 1px solid #CCC;\n  border-right: 1px solid #CCC;\n  /*height: 500px;\n  width: 320px;*/\n  height: 100%;\n  width: 100%;\n  /*margin: 2rem auto;*/\n  display: flex;\n  flex-direction: column;\n  font-family: \"helvetica\", sans-serif;\n}\n#message_window .disconnected {\n  background: #FFFFCC;\n  padding: 0.25rem;\n}\n#message_window.connected .disconnected {\n  display: none;\n}\n#message_window .offline {\n  display: none;\n}\n#message_window.offline .disconnected {\n  display: none;\n}\n#message_window.offline .offline {\n  background: #FF0000;\n  color: #FFF;\n  padding: 0.25rem;\n  display: block;\n}\n#message_window .powered_by {\n  flex-shrink: 0;\n  text-align: center;\n  border-bottom: 1px solid #CCC;\n  font-size: 14px;\n  padding: 0.25rem;\n  color: #666;\n}\n#message_window .powered_by a {\n  text-decoration: none;\n  color: #666;\n}\n#message_window .powered_by img {\n  position: relative;\n  top: 2px;\n}\n#message_window section {\n  flex-grow: 1;\n  flex-direction: column-reverse;\n  display: flex;\n  overflow-y: auto;\n}\n#message_window section div div {\n  margin: 0.25rem;\n  clear: both;\n}\n#message_window footer {\n  border-top: 1px solid #CCC;\n  padding: 0.25rem;\n}\n#message_window footer input[type=text] {\n  flex-grow: 1;\n  font-size: 1.25rem;\n  outline: none;\n  border: none;\n}\n#message_window footer button {\n  width: 50px;\n  background: none;\n  border: 0;\n  cursor: pointer;\n  color: blue;\n  font-weight: bold;\n}\n#message_window form {\n  display: flex;\n  margin: 0;\n  padding: 0.25rem;\n}\n#message_window #message_template {\n  display: none;\n}\n#message_window .message {\n  font-size: 14px;\n  padding: 0.5rem;\n  background: #F0F0F0;\n  color: #333;\n  border-radius: 5px;\n  width: auto;\n  display: inline-block;\n  max-width: 75%;\n}\n#message_window .file_attachment {\n  background: #F0F0F0;\n  color: #333;\n  border-radius: 5px;\n  display: inline-block;\n  max-width: 75%;\n}\n#message_window .file_attachment img {\n  max-width: 100%;\n  display: block;\n}\n#message_window .button_message {\n  margin: 1rem 0;\n  border-radius: 4px;\n  border-color: orange;\n  border-style: solid;\n  color: orange;\n  border-width: 1px;\n  padding: 0.25rem 1rem;\n  text-decoration: none;\n  text-align: center;\n  box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.25);\n  display: block;\n}\n#message_window .message p {\n  margin-top: 0;\n  margin-bottom: 0.5rem;\n}\n#message_window .message p:last-child {\n  margin-bottom: 0;\n}\n#message_window .message.outgoing {\n  float: right;\n  background: #a795ef;\n  color: white;\n}\n#message_window #message_replies {\n  text-align: center;\n  overflow-x: auto;\n  flex-shrink: 0;\n  -webkit-overflow-scrolling: touch;\n  /* Lets it scroll lazy */\n}\n#message_window #message_replies ul {\n  list-style-type: none;\n  margin: 0px auto;\n  padding: 0;\n}\n#message_window #message_replies ul li {\n  display: inline-block;\n  margin: 0.5rem;\n  margin-left: 0;\n}\n#message_window #message_replies a {\n  text-decoration: none;\n  display: block;\n  border: 1px solid #a795ef;\n  color: #a795ef;\n  border-radius: 16px;\n  padding: 0.25rem 1rem;\n  font-size: 14px;\n  cursor: pointer;\n}\n#message_window #message_replies a:hover {\n  background: #a795ef;\n  color: #FFF;\n}\n\n/* typing indicator CSS based on code by Joseph Fusco -> https://codepen.io/fusco/pen/XbpaYv */\n.typing-indicator {\n  display: table;\n  margin: 0 auto;\n  position: relative;\n}\n.typing-indicator span {\n  height: 5px;\n  width: 5px;\n  float: left;\n  margin: 0 1px;\n  background-color: #333;\n  display: block;\n  border-radius: 50%;\n  opacity: 0.4;\n}\n.typing-indicator span:nth-of-type(1) {\n  animation: 1s blink infinite 0.3333s;\n}\n.typing-indicator span:nth-of-type(2) {\n  animation: 1s blink infinite 0.6666s;\n}\n.typing-indicator span:nth-of-type(3) {\n  animation: 1s blink infinite 0.9999s;\n}\n\n@keyframes blink {\n  50% {\n    opacity: 1;\n  }\n}\n/* special styles for homepage */\n#home {\n  position: relative;\n  max-width: 650px;\n  margin: auto;\n}\n#home:after {\n  content: \"\";\n  display: table;\n  clear: both;\n}\n\n#homepage_bot {\n  width: 400px;\n  height: 450px;\n  float: left;\n  border: 5px solid #333;\n  box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.5);\n}\n#homepage_bot iframe {\n  border: 0;\n  height: 100%;\n  width: 100%;\n}\n\n#welcome {\n  margin-left: 440px;\n}\n\n/*# sourceMappingURL=styles.css.map */\n"
  },
  {
    "path": "packages/testbot/public/index.html",
    "content": "<html>\n    <head>\n        <title>Botkit Anywhere</title>\n        <script src=\"https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.10/handlebars.min.js\"></script>\n        <script src=\"https://cdn.rawgit.com/showdownjs/showdown/1.7.4/dist/showdown.min.js\"></script>\n        <link rel=\"stylesheet\" href=\"/css/styles.css\" />\n        <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    </head>\n    <body >\n      <div class=\"wrapper\">\n\n        <div id=\"message_window\">\n            <div class=\"disconnected\">\n                Disconnected... reconnecting!\n            </div>\n            <div class=\"offline\">\n                Offline! Reload to reconnect.\n            </div>\n            <div class=\"powered_by\">\n              Powered by <a href=\"https://botkit.ai\" target=\"_blank\" title=\"Building Blocks for Building Bots\"><img src=\"/botkit_icon.png\" width=\"15\" height=\"15\" alt=\"Botkit Logo\" /> Botkit</a>\n            </div>\n            <section>\n                <div id=\"message_list\">\n                    <div id=\"message_template\">\n                        <div class=\"message {{message.type}}\">\n                            {{#if message.isTyping}}\n                              <div class=\"typing-indicator\">\n                                <span></span>\n                                <span></span>\n                                <span></span>\n                              </div>\n                            {{/if}}\n                            {{{message.html}}}\n\n                            {{#if message.open_link}}\n                              <a href=\"{{{message.open_link}}}\" target=\"_blank\" class=\"button_message\">{{#if message.link_title}}{{message.link_title}}{{else}}{{message.open_link}}{{/if}}</a>\n                            {{/if}}\n                        </div>\n                        {{#message.files}}\n                          <div class=\"file_attachment\">\n                          {{#if image}}\n                            <img src=\"{{{url}}}\" alt=\"{{{url}}}\" />\n                          {{else}}\n                            <a href=\"{{{url}}}\" title=\"{{{url}}}\">{{{url}}}</a>\n                          {{/if}}\n                          </div>\n                        {{/message.files}}\n                    </div>\n                </div>\n            </section>\n            <div id=\"message_replies\">\n            </div>\n            <footer>\n                <form onsubmit=\"Botkit.send(Botkit.input.value, event)\">\n                    <input type=\"text\" autocomplete=\"off\" id=\"messenger_input\" placeholder=\"Type here...\" />\n                    <button type=\"submit\">Send</button>\n                </form>\n            </footer>\n        </div>\n        </div>\n        <script src=\"/client.js\"></script>\n    </body>\n</html>"
  },
  {
    "path": "packages/testbot/testbot.bot",
    "content": "{\n    \"name\": \"testbot.bot\",\n    \"description\": \"\",\n    \"services\": [\n        {\n            \"type\": \"endpoint\",\n            \"appId\": \"\",\n            \"appPassword\": \"\",\n            \"endpoint\": \"http://localhost:3000/api/messages\",\n            \"id\": \"b9a54960-1f51-11e9-8939-03499153c69d\",\n            \"name\": \"http://localhost:3000/api/messages\"\n        }\n    ],\n    \"padlock\": \"\",\n    \"version\": \"2.0\",\n    \"overrides\": null\n}\n"
  },
  {
    "path": "readme.md",
    "content": "# ![Botkit](banner.png)\n\n**Botkit is an open source developer tool for building chat bots, apps and custom integrations for major messaging platforms.**\n\nThis repository contains the core Botkit library, as well as a series of plugins and extensions for connecting Botkit to messaging and chat platforms and other tools in the bot building ecosystem.\n\nBotkit is part of the [Microsoft Bot Framework](https://dev.botframework.com)\nand is released under the [MIT Open Source license](LICENSE.md)\n\n# Use Botkit\n\n* [Install Botkit and get started](packages/botkit#readme)\n* [Botkit Core Docs](https://github.com/howdyai/botkit/blob/main/packages/docs/index.md)\n* [Botkit Platform Support](https://github.com/howdyai/botkit/blob/main/packages/docs/platforms/index.md)\n* [Botkit Class Reference](https://github.com/howdyai/botkit/blob/main/packages/docs/reference/index.md)\n\n## Packages included in this repo\n\n| Package | Description | NPM Status\n|--- |--- |---\n| [botkit](packages/botkit) | Botkit Core library | [![NPM Badge](https://img.shields.io/npm/dw/botkit.svg?logo=npm)](https://www.npmjs.com/package/botkit/) \n| [botbuilder-adapter-web](packages/botbuilder-adapter-web) | A platform adapter for the web | [![NPM Badge](https://img.shields.io/npm/dw/botbuilder-adapter-web.svg?logo=npm)](https://www.npmjs.com/package/botbuilder-adapter-web) \n| [botbuilder-adapter-slack](packages/botbuilder-adapter-slack) | A platform adapter for Slack | [![NPM Badge](https://img.shields.io/npm/dw/botbuilder-adapter-slack.svg?logo=npm)](https://www.npmjs.com/package/botbuilder-adapter-slack) \n| [botbuilder-adapter-webex](packages/botbuilder-adapter-webex) | A platform adapter for Webex Teams | [![NPM Badge](https://img.shields.io/npm/dw/botbuilder-adapter-webex.svg?logo=npm)](https://www.npmjs.com/package/botbuilder-adapter-webex) \n| [botbuilder-adapter-hangouts](packages/botbuilder-adapter-hangouts) | A platform adapter for Google  | [![NPM Badge](https://img.shields.io/npm/dw/botbuilder-adapter-hangouts.svg?logo=npm)](https://www.npmjs.com/package/botbuilder-adapter-hangouts)\n| [botbuilder-adapter-twilio-sms](packages/botbuilder-adapter-twilio-sms) | A platform adapter for Twilio SMS | [![NPM Badge](https://img.shields.io/npm/dw/botbuilder-adapter-twilio-sms.svg?logo=npm)](https://www.npmjs.com/package/botbuilder-adapter-twilio-sms) \n| [botbuilder-adapter-facebook](packages/botbuilder-adapter-facebook) | A platform adapter for Facebook Messenger | [![NPM Badge](https://img.shields.io/npm/dw/botbuilder-adapter-facebook.svg?logo=npm)](https://www.npmjs.com/package/botbuilder-adapter-facebook) \n| [generator-botkit](packages/generator-botkit) | A Yeoman generator for creating a new Botkit project | [![NPM Badge](https://img.shields.io/npm/dw/generator-botkit.svg?logo=npm)](https://www.npmjs.com/package/generator-botkit) \n| [botkit-plugin-cms](packages/botkit-plugin-cms) | A plugin that adds support for [Botkit CMS](https://github.com/howdyai/botkit-cms) | [![NPM Badge](https://img.shields.io/npm/dw/botkit-plugin-cms.svg?logo=npm)](https://www.npmjs.com/package/botkit-plugin-cms)\n\n## Build Botkit locally\n\nThis repo contains multiple inter-linked packages containing Botkit Core, platform adapter packages, and some additional plugins and extensions.\nTo build these locally, follow the instructions below.\n\nInstall [lerna](https://github.com/lerna/lerna) and [TypeScript](https://www.typescriptlang.org/) globally:\n\n```bash\nnpm install -g typescript\nnpm install -g lerna\n```\n\nClone the entire Botkit project from Github.\n\n```bash\ngit clone git@github.com:howdyai/botkit.git\n```\n\nEnter the new folder and install the dependent packages:\n\n```bash\ncd botkit\nnpm install\n```\n\nUse lerna to set up the local packages:\n\n```bash\nlerna bootstrap --hoist\n```\n\nNow, build all of the libraries:\n\n```bash\nlerna run build\n```\n\nTo build updated versions of the class reference documents found in `packages/docs`, run:\n\n```bash\nlerna run build-docs\n```\n"
  },
  {
    "path": "todo.md",
    "content": "# packages\n\n    * move/remove/ignore testbot\n\n# core\n# docs\n\n# advanced topics\n    * anatomy\n    * upgrade guide\n\n    * every adapter doc should link to main client API doc\n    * link to provisioning guides\n\n# github\n\n    * tag new v4 branch\n\n# starter kits / yeoman\n\n    * move over more useful skills\n\n# Teams \n\n    * direct_message qualifications\n    * update/remove message in botworker?\n\n    * -> https://github.com/howdyai/botkit/blob/master/lib/TeamsAPI.js\n    * getchannels <-- can be achieved but is different/ and not compatible with getconversations\n    * getuserbyid <-- predicated on getconvo members\n    * getuserbyupn <-- see above\n    * getconversationmembers <-- works but awkward\n    * getteamroster <-- works but awkward\n    * gettoken? <-- works but awkard>\n\n\n# Tests!\n\n# POST LAUNCH\n\n    * update cms \"options\" page to reflect use with botkit-plugin-cms\n    * botbuilder card builders?\n    * ears? check for intent, others?\n    * how to determine what is active dialog / do contextual help"
  }
]