├── .editorconfig ├── .eslintrc.json ├── .github └── dependabot.yml ├── .gitignore ├── LICENSE ├── README.md ├── css └── dist-editor-dark.css ├── debug.sh ├── examples ├── apicall.md ├── calculator.md ├── filesystem.md ├── help.md ├── introspection.md ├── javascript.md ├── metadata.md ├── plugin.md ├── readpdf.md ├── restrictions.md ├── retrieve.md ├── retrievepdf.md ├── savetext.md ├── search.md ├── search2.md ├── security.md ├── shakespeare.md └── vim.md ├── go.sh ├── index.mjs ├── js └── _dist-editor.js ├── lib ├── Groups.js ├── anthropic.mjs ├── colour.mjs ├── openai.mjs └── tools.mjs ├── merge.txt ├── package-lock.json ├── package.json ├── plugin.txt └── prompt.txt /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | indent_style = space 6 | indent_size = 2 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "es6": true, 4 | "node": true, 5 | "mocha": true 6 | }, 7 | "extends": "eslint:recommended", 8 | "parser": "@typescript-eslint/parser", 9 | "parserOptions": { 10 | "ecmaVersion": 2017, 11 | "sourceType": "module" 12 | }, 13 | "globals": { 14 | "import": true, 15 | "ReadableStream": true 16 | }, 17 | "rules": { 18 | "accessor-pairs": "error", 19 | "array-bracket-spacing": [ 20 | "off", 21 | "never" 22 | ], 23 | "array-callback-return": "error", 24 | "arrow-body-style": "off", 25 | "arrow-parens": [ 26 | "off", 27 | "as-needed" 28 | ], 29 | "arrow-spacing": [ 30 | "error", 31 | { 32 | "after": true, 33 | "before": true 34 | } 35 | ], 36 | "block-scoped-var": "off", 37 | "block-spacing": "off", 38 | "brace-style": [ 39 | "off", 40 | "stroustrup" 41 | ], 42 | "callback-return": "off", 43 | "camelcase": "off", 44 | "class-methods-use-this": "error", 45 | "comma-dangle": "error", 46 | "comma-spacing": "off", 47 | "comma-style": [ 48 | "error", 49 | "last" 50 | ], 51 | "complexity": "off", 52 | "computed-property-spacing": [ 53 | "error", 54 | "never" 55 | ], 56 | "consistent-return": "off", 57 | "consistent-this": "error", 58 | "curly": "off", 59 | "default-case": "error", 60 | "dot-location": [ 61 | "off", 62 | "property" 63 | ], 64 | "dot-notation": [ 65 | "error", 66 | { 67 | "allowKeywords": true 68 | } 69 | ], 70 | "eol-last": "error", 71 | "eqeqeq": "off", 72 | "func-call-spacing": "off", 73 | "func-name-matching": "off", 74 | "func-names": "off", 75 | "func-style": [ 76 | "off", 77 | "declaration" 78 | ], 79 | "generator-star-spacing": "off", 80 | "global-require": "off", 81 | "guard-for-in": "off", 82 | "handle-callback-err": "off", 83 | "id-blacklist": "error", 84 | "id-length": "off", 85 | "id-match": "error", 86 | "indent": "off", 87 | "init-declarations": "off", 88 | "jsx-quotes": "error", 89 | "key-spacing": "off", 90 | "keyword-spacing": ["error", { "after": true }], 91 | "line-comment-position": "off", 92 | "linebreak-style": [ 93 | "error", 94 | "unix" 95 | ], 96 | "lines-around-comment": "off", 97 | "lines-around-directive": "off", 98 | "max-depth": "off", 99 | "max-len": "off", 100 | "max-lines": "off", 101 | "max-nested-callbacks": "error", 102 | "max-params": "off", 103 | "max-statements": "off", 104 | "max-statements-per-line": "off", 105 | "multiline-ternary": [ 106 | "off", 107 | "never" 108 | ], 109 | "new-parens": "error", 110 | "newline-after-var": "off", 111 | "newline-before-return": "off", 112 | "newline-per-chained-call": "off", 113 | "no-alert": "error", 114 | "no-array-constructor": "error", 115 | "no-async-promise-executor": "warn", 116 | "no-bitwise": "off", 117 | "no-caller": "error", 118 | "no-catch-shadow": "off", 119 | "no-confusing-arrow": "error", 120 | "no-console": "off", 121 | "no-constant-condition": "off", 122 | "no-continue": "off", 123 | "no-control-regex": "off", 124 | "no-debugger": "off", 125 | "no-div-regex": "error", 126 | "no-duplicate-imports": "error", 127 | "no-else-return": "off", 128 | "no-empty": [ 129 | "warn", 130 | { 131 | "allowEmptyCatch": true 132 | } 133 | ], 134 | "no-empty-function": "off", 135 | "no-eq-null": "error", 136 | "no-eval": "error", 137 | "no-extend-native": "off", 138 | "no-extra-bind": "error", 139 | "no-extra-label": "error", 140 | "no-extra-parens": "off", 141 | "no-floating-decimal": "error", 142 | "no-global-assign": "error", 143 | "no-implicit-globals": "error", 144 | "no-implied-eval": "error", 145 | "no-inline-comments": "off", 146 | "no-inner-declarations": [ 147 | "off", 148 | "functions" 149 | ], 150 | "no-invalid-this": "off", 151 | "no-iterator": "error", 152 | "no-label-var": "error", 153 | "no-labels": "error", 154 | "no-lone-blocks": "error", 155 | "no-lonely-if": "off", 156 | "no-loop-func": "off", 157 | "no-magic-numbers": "off", 158 | "no-mixed-operators": "error", 159 | "no-mixed-requires": "error", 160 | "no-multi-spaces": "off", 161 | "no-multi-str": "error", 162 | "no-multiple-empty-lines": "error", 163 | "no-negated-condition": "error", 164 | "no-nested-ternary": "off", 165 | "no-new": "error", 166 | "no-new-func": "error", 167 | "no-new-object": "error", 168 | "no-new-require": "error", 169 | "no-new-wrappers": "error", 170 | "no-octal-escape": "error", 171 | "no-param-reassign": "off", 172 | "no-path-concat": "error", 173 | "no-plusplus": "off", 174 | "no-process-env": "off", 175 | "no-process-exit": "off", 176 | "no-proto": "error", 177 | "no-prototype-builtins": "off", 178 | "no-restricted-globals": "error", 179 | "no-restricted-imports": "error", 180 | "no-restricted-modules": "error", 181 | "no-restricted-properties": "error", 182 | "no-restricted-syntax": "error", 183 | "no-return-assign": "off", 184 | "no-script-url": "error", 185 | "no-self-compare": "error", 186 | "no-sequences": "error", 187 | "no-shadow": "off", 188 | "no-shadow-restricted-names": "error", 189 | "no-spaced-func": "off", 190 | "no-sync": "off", 191 | "no-tabs": "off", 192 | "no-template-curly-in-string": "off", 193 | "no-ternary": "off", 194 | "no-throw-literal": "error", 195 | "no-trailing-spaces": "error", 196 | "no-undef-init": "error", 197 | "no-undefined": "off", 198 | "no-underscore-dangle": "off", 199 | "no-unmodified-loop-condition": "error", 200 | "no-unneeded-ternary": [ 201 | "error", 202 | { 203 | "defaultAssignment": true 204 | } 205 | ], 206 | "no-unsafe-negation": "error", 207 | "no-unused-expressions": "error", 208 | "no-unused-vars": "off", 209 | "no-use-before-define": "off", 210 | "no-useless-call": "error", 211 | "no-useless-computed-key": "error", 212 | "no-useless-concat": "off", 213 | "no-useless-constructor": "error", 214 | "no-useless-escape": "off", 215 | "no-useless-rename": "error", 216 | "no-var": "off", 217 | "no-void": "error", 218 | "no-warning-comments": "off", 219 | "no-whitespace-before-property": "error", 220 | "no-with": "error", 221 | "object-curly-newline": "off", 222 | "object-curly-spacing": "off", 223 | "object-property-newline": [ 224 | "off", 225 | { 226 | "allowMultiplePropertiesPerLine": true 227 | } 228 | ], 229 | "object-shorthand": "off", 230 | "one-var": "off", 231 | "one-var-declaration-per-line": "error", 232 | "operator-assignment": "off", 233 | "operator-linebreak": "off", 234 | "padded-blocks": "off", 235 | "prefer-arrow-callback": "off", 236 | "prefer-const": "off", 237 | "prefer-numeric-literals": "error", 238 | "prefer-reflect": "off", 239 | "prefer-rest-params": "error", 240 | "prefer-spread": "error", 241 | "prefer-template": "off", 242 | "quote-props": "off", 243 | "quotes": "off", 244 | "radix": "error", 245 | "require-jsdoc": "off", 246 | "require-yield": "off", 247 | "rest-spread-spacing": "off", 248 | "semi": "off", 249 | "semi-spacing": "off", 250 | "sort-imports": "off", 251 | "sort-keys": "off", 252 | "sort-vars": "off", 253 | "space-before-blocks": "off", 254 | "space-before-function-paren": "off", 255 | "space-in-parens": [ 256 | "error", 257 | "never" 258 | ], 259 | "space-infix-ops": "off", 260 | "space-unary-ops": "error", 261 | "spaced-comment": "off", 262 | "strict": "off", 263 | "symbol-description": "error", 264 | "template-curly-spacing": "error", 265 | "unicode-bom": [ 266 | "error", 267 | "never" 268 | ], 269 | "valid-jsdoc": "off", 270 | "vars-on-top": "off", 271 | "wrap-iife": "error", 272 | "wrap-regex": "off", 273 | "yield-star-spacing": "error", 274 | "yoda": [ 275 | "error", 276 | "never" 277 | ] 278 | } 279 | } 280 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "npm" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "weekly" 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env 3 | history.yaml 4 | *.html 5 | *.pdf 6 | .DS_Store 7 | temp.png 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2023 Postman, inc. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🕵️🔗 BingChain 2 | 3 | This is an evolution of [langchain-mini](https://github.com/ColinEberhardt/langchain-mini), a very simple re-implementation of [LangChain](https://github.com/hwchase17/langchain), in ~350 lines of core code. In essence, it is a multi-model LLM-powered chat application that is able to use tools (Microsoft **Bing** search, URL retrieval, API plugin installation, API calls, a Javascript sandbox, JsFiddle creation, image and video preview, and a scientific calculator, as well as meta-tools such as `list`, `disable`, `reset` and `debug`) in order to build a **chain** of thought to hold conversations and answer questions. 4 | 5 | Here's an example: 6 | 7 | ~~~ 8 | Q: What is the world record for solving a rubiks cube? 9 | The world record for solving a Rubik's Cube is 4.69 seconds, held by Yiheng Wang (China). 10 | Q: Can a robot solve it faster? 11 | The fastest time a robot has solved a Rubik's Cube is 0.637 seconds. 12 | Q: Who made this robot? 13 | Infineon created the robot that solved a Rubik's Cube in 0.637 seconds. 14 | Q: What time would an average human expect for solving? 15 | It takes the average person about three hours to solve a Rubik's cube for the first time. 16 | ~~~ 17 | 18 | This is not intended to be a replacement for LangChain, which has many alternative and composable building blocks, instead it was built to demonstrate the power of assembling a set of tools (such as API calling and Javascript execution). If you're interested in how LangChain, and similar tools work, this is a very good starting point. 19 | 20 | ## Running / developing 21 | 22 | Install dependencies, and run (with node >= v18): 23 | 24 | ~~~ 25 | % npm install 26 | ~~~ 27 | 28 | To display videos in the terminal, you will need to install `ffmpeg`. 29 | 30 | You'll need to have an OpenAI API key, and optionally a Bing Search API key. These can be supplied to the application via a `.env` file: 31 | 32 | ```shell 33 | OPENAI_API_KEY="..." 34 | BING_API_KEY="..." 35 | MODEL=gpt-4 36 | TOKEN_LIMIT=32768 37 | TEMPERATURE=0.25 38 | RESPONSE_LIMIT=512 39 | PORT=1337 40 | GUI=1 41 | #LANG=Ukrainian 42 | #DEBUG=2 43 | #SEED_QUERIES=1 44 | #PROMPT_OVERRIDE=Riddle me this! ${question} 45 | ``` 46 | 47 | You can also set `PROVIDER=anthropic` (with a relevant `ANTHROPIC_API_KEY`, `MODEL` and `TOKEN_LIMIT`) to use an alternative LLM/API provider. 48 | 49 | Set the token limit to the advertised limit of the model you are using, so 32768 for `gpt-4`, 4096 for `text-davinci-003` and 2048 for `text-curie-001`. 50 | 51 | The clever part is the default initial prompt, which is held in [`prompt.txt`](https://raw.githubusercontent.com/postman-open-technologies/bingchain/main/prompt.txt), unless overridden by the `PROMPT_OVERRIDE` environment variable. 52 | 53 | Example prompts and responses to show how the various built-in tools work can be found in the [`examples`](https://github.com/postman-open-technologies/bingchain/tree/main/examples) directory. The tools themselves are defined in [`lib/tools.mjs`](https://github.com/postman-open-technologies/bingchain/tree/main/lib/tools.mjs), including the `description` properties which act as further prompts to the LLM to suggest when and how the tools should be used. 54 | 55 | There are a few Javascript and CSS files scattered about from [jsfiddle.net](https://jsfiddle.net/) to make the `savetext`, `savehtml` and `savecode` tools work locally. 56 | 57 | **Note**: to enable the Javascript sandbox, you must pass the option `--experimental-vm-modules` to Node.js. The included `go.sh` script sets the Node.js recommended options. 58 | 59 | ## Start-up 60 | 61 | The application will display the built-in tools as it initialises them. Tool names followed by [1] are disabled by default for security reasons (i.e. they may access files on your local filesystem or your environment variables). You can enable them by typing `enable [toolname]` at the prompt. Tool names followed by [2] are disabled becuase you do not have the requisite API key in your environment or your version of Node.js does not support the required features. 62 | 63 | ## Example dialogue 64 | 65 | You can now run the chain: 66 | 67 | ```repl 68 | % ./go.sh 69 | How can I help? > what was the name of the first woman in space? 70 | ``` 71 | 72 | * I need to search for the name of the first woman in space. 73 | * *Action*: `search` 74 | * *Action Input*: `first woman in space name` 75 | 76 | Calling `search` with `first woman in space name` 77 | 78 | 1. **Valentina Tereshkova - First Woman in Space - Biography** 79 | 2. **Valentina Tereshkova: First Woman in Space | Space** 80 | 3. **The First Woman in Space: Valentina Tereshkova - ThoughtCo** 81 | 82 | * *Thought*: I now know the final answer. 83 | * *Final Answer*: The name of the first woman in space is Valentina Tereshkova. 84 | * **The name of the first woman in space is Valentina Tereshkova.** 85 | 86 | ### Exiting the chain / vi mode 87 | 88 | * You can use `vi`/`vim`-like commands to exit, such as `:q` or you can Ctrl-C twice to exit. 89 | * You can use `:set` to query all environment variables or `:set [variable]=[value]` to temporarily amend the current environment. 90 | 91 | ## Authors 92 | 93 | * [Mike Ralphson](https://github.com/MikeRalphson) 94 | * [Gbadeyboh Bello](https://github.com/Gbahdeyboh) 95 | * [Colin Eberhardt](https://github.com/ColinEberhardt) 96 | 97 | ## Future work planned 98 | 99 | * Ideas and PRs gratefully received. 100 | -------------------------------------------------------------------------------- /css/dist-editor-dark.css: -------------------------------------------------------------------------------- 1 | .ui-mprogress{pointer-events:none}.ui-mprogress .bar-bg,.ui-mprogress .buffer-bg,.ui-mprogress .deter-bar,.ui-mprogress .indeter-bar,.ui-mprogress .mp-ui-dashed,.ui-mprogress .query-bar{position:fixed;z-index:1032;top:0;left:0;width:100%;height:3px;background:#0084ff}.ui-mprogress .bar-bg,.ui-mprogress .buffer-bg{z-index:1031;background:rgba(0,132,255,.2)}.ui-mprogress .mp-ui-dashed{z-index:1030;background:transparent}.ui-mprogress .mp-ui-dashed:before{content:"";display:block;height:3px;width:100%;margin-top:0;position:absolute;background:radial-gradient(#a9c0e9 0,#a9c0e9 16%,transparent 42%);background-size:10px 10px!important;background-position:0 -23px;animation:buffer 3s infinite linear}.ui-mprogress .peg{position:absolute;display:block;right:0;width:100px;height:100%;box-shadow:0 0 10px #0084ff,0 0 5px #29d;opacity:1;transform:rotate(3deg) translateY(-4px)}.ui-mprogress .query-bar{animation:querying 2.8s infinite linear}.ui-mprogress .query-bar.end{animation:endquery 1.5s linear}.ui-mprogress .indeter-bar{animation:indeterminate 2.8s infinite linear}.mprogress-custom-parent{overflow:hidden;position:relative}.mprogress-custom-parent .bar-bg,.mprogress-custom-parent .buffer-bg,.mprogress-custom-parent .deter-bar,.mprogress-custom-parent .indeter-bar,.mprogress-custom-parent .mp-ui-dashed,.mprogress-custom-parent .query-bar{position:absolute}@keyframes querying{0%{transform:translateX(100%) scaleX(.7)}20%{transform:translateX(30%) scaleX(.7)}30%{transform:translateX(-20%) scaleX(.4)}55%{transform:translateX(-100%) scaleX(.1)}55.99%{transform:scaleX(0)}56%{transform:translateX(100%) scaleX(0)}56.99%{transform:translateX(100%) scaleX(.7)}70%{transform:translateX(35%) scaleX(.7)}85%{transform:translateX(-28%) scaleX(.3)}95%{transform:translateX(-100%) scaleX(.1)}95.99%{transform:scaleX(0)}to{transform:translateX(100%)}}@keyframes endquery{0%{opacity:0;transform:translateX(-100%) scaleX(1)}10%{opacity:1;transform:translateX(-100%) scaleX(1)}99%{opacity:1;transform:translateX(0)}to{opacity:0}}@keyframes indeterminate{0%{transform:translateX(-100%) scaleX(.2)}20%{transform:translateX(-40%) scaleX(.2)}30%{transform:translateX(0) scaleX(.5)}55%{transform:translateX(100%) scaleX(.7)}55.99%{transform:scaleX(0)}56%{transform:translateX(-100%) scaleX(0)}56.99%{transform:translateX(-100%) scaleX(.6)}75%{transform:translateX(-5%) scaleX(.6)}85%{transform:translateX(30%) scaleX(.3)}98%{transform:translateX(100%) scaleX(.2)}99.99%{transform:scaleX(0)}to{transform:translateX(-100%)}}@keyframes buffer{0%{opacity:1;background-position:0 -23px}50%{opacity:0}to{opacity:1;background-position:-200px -23px}}.CodeMirror{font-family:monospace;height:300px;color:#000;direction:ltr}.CodeMirror-lines{padding:4px 0}.CodeMirror pre{padding:0 4px}.CodeMirror-gutter-filler,.CodeMirror-scrollbar-filler{background-color:#fff}.CodeMirror-gutters{border-right:1px solid #ddd;background-color:#f7f7f7;white-space:nowrap}.CodeMirror-linenumber{padding:0 3px 0 5px;min-width:20px;text-align:right;color:#999;white-space:nowrap}.CodeMirror-guttermarker{color:#000}.CodeMirror-guttermarker-subtle{color:#999}.CodeMirror-cursor{border-left:2px solid #fff;border-right:none;width:0}.CodeMirror div.CodeMirror-secondarycursor{border-left:1px solid silver}.cm-fat-cursor .CodeMirror-cursor{width:auto;border:0!important;background:#7e7}.cm-fat-cursor div.CodeMirror-cursors{z-index:1}.cm-fat-cursor-mark{background-color:rgba(20,255,20,.5);animation:blink 1.06s steps(1) infinite}.cm-animate-fat-cursor{width:auto;border:0;animation:blink 1.06s steps(1) infinite;background-color:#7e7}@keyframes blink{50%{background-color:transparent}}.cm-tab{display:inline-block;text-decoration:inherit}.CodeMirror-rulers{position:absolute;left:0;right:0;top:-50px;bottom:-20px;overflow:hidden}.CodeMirror-ruler{border-left:1px solid #ccc;top:0;bottom:0;position:absolute}.CodeMirror{position:relative;background:#fff}.CodeMirror-scroll{overflow:scroll!important;margin-bottom:-30px;margin-right:-30px;padding-bottom:30px;height:100%;outline:none;position:relative}.CodeMirror-sizer{position:relative;border-right:30px solid transparent}.CodeMirror-gutter-filler,.CodeMirror-hscrollbar,.CodeMirror-scrollbar-filler,.CodeMirror-vscrollbar{position:absolute;z-index:6;display:none}.CodeMirror-vscrollbar{right:0;top:0;overflow-x:hidden;overflow-y:scroll}.CodeMirror-hscrollbar{bottom:0;left:0;overflow-y:hidden;overflow-x:scroll}.CodeMirror-scrollbar-filler{right:0;bottom:0}.CodeMirror-gutter-filler{left:0;bottom:0}.CodeMirror-gutters{position:absolute;left:0;top:0;min-height:100%;z-index:3}.CodeMirror-gutter{white-space:normal;height:100%;display:inline-block;vertical-align:top;margin-bottom:-30px}.CodeMirror-gutter-wrapper{position:absolute;z-index:4;background:none!important;border:none!important}.CodeMirror-gutter-background{position:absolute;top:0;bottom:0;z-index:4}.CodeMirror-gutter-elt{position:absolute;cursor:default;z-index:4}.CodeMirror-gutter-wrapper ::selection{background-color:transparent}.CodeMirror-gutter-wrapper ::-moz-selection{background-color:transparent}.CodeMirror-lines{cursor:text;min-height:1px}.CodeMirror pre{border-radius:0;border-width:0;background:transparent;font-family:inherit;font-size:inherit;margin:0;white-space:pre;word-wrap:normal;line-height:inherit;color:inherit;z-index:2;position:relative;overflow:visible;-webkit-tap-highlight-color:transparent;font-variant-ligatures:contextual}.CodeMirror-wrap pre{word-wrap:break-word;white-space:pre-wrap;word-break:break-all}.CodeMirror-linebackground{position:absolute;left:0;right:0;top:0;bottom:0;z-index:0}.CodeMirror-linewidget{position:relative;z-index:2;padding:.1px}.CodeMirror-rtl pre{direction:rtl}.CodeMirror-code{outline:none}.CodeMirror-gutter,.CodeMirror-gutters,.CodeMirror-linenumber,.CodeMirror-scroll,.CodeMirror-sizer{box-sizing:content-box}.CodeMirror-measure{position:absolute;width:100%;height:0;overflow:hidden;visibility:hidden}.CodeMirror-cursor{position:absolute;pointer-events:none}.CodeMirror-measure pre{position:static}div.CodeMirror-cursors{visibility:hidden;position:relative;z-index:3}.CodeMirror-focused div.CodeMirror-cursors,div.CodeMirror-dragcursors{visibility:visible}.CodeMirror-selected{background:#d9d9d9}.CodeMirror-focused .CodeMirror-selected{background:#d7d4f0}.CodeMirror-crosshair{cursor:crosshair}.CodeMirror-line::selection,.CodeMirror-line>span::selection,.CodeMirror-line>span>span::selection{background:#d7d4f0}.CodeMirror-line::-moz-selection,.CodeMirror-line>span::-moz-selection,.CodeMirror-line>span>span::-moz-selection{background:#d7d4f0}.cm-searching{background-color:#ffa;background-color:rgba(255,255,0,.4)}.cm-force-border{padding-right:.1px}@media print{.CodeMirror div.CodeMirror-cursors{visibility:hidden}}.cm-tab-wrap-hack:after{content:""}span.CodeMirror-selectedtext{background:none}.CodeMirror-lint-markers{width:16px}.CodeMirror-lint-tooltip{background:#1a1d21;border-radius:4px;font-size:13px;line-height:1.52em;color:#cfd0d1;overflow:hidden;padding:10px 14px;position:fixed;white-space:pre;white-space:pre-wrap;z-index:100;max-width:600px;opacity:0;transition:opacity .15s}.CodeMirror-lint-mark-error{border-bottom:2px solid #bf5b74}.CodeMirror-lint-mark-warning{border-bottom:2px solid #f3ca63}.CodeMirror-lint-marker-error,.CodeMirror-lint-marker-warning{cursor:pointer;display:inline-block;height:6px;width:6px;vertical-align:middle;position:relative;border-radius:20px;left:10px}.CodeMirror-lint-message-error:before,.CodeMirror-lint-message-warning:before{content:"";display:inline-block;height:6px;width:6px;vertical-align:middle;position:relative;border-radius:20px;margin-right:10px}.CodeMirror-lint-message-error:before{background:#bf5b74}.CodeMirror-lint-message-warning:before{background:#f3ca63}.CodeMirror-lint-marker-error{background:#bf5b74}.CodeMirror-lint-marker-warning{background:#f3ca63}.CodeMirror-lint-marker-multiple{width:100%;height:100%}.CodeMirror-hints{position:absolute;z-index:300;overflow:hidden;padding:2px;box-shadow:0 5px 15px rgba(0,0,0,.1);border-radius:4px;border:1px solid #2c2f34;background:rgba(26,29,33,.95);font-family:"SF Mono","Monaco","Andale Mono","Lucida Console","Bitstream Vera Sans Mono","Courier New",Courier,monospace;font-size:11px;max-height:20em;overflow-y:auto}.CodeMirror-hint{padding:5px 8px;border-radius:3px;white-space:pre;color:#cfd0d1;cursor:pointer}li.CodeMirror-hint-active{background:#2e71ff;color:#fff}.choices{position:relative;margin-bottom:0;font-size:16px}.choices:focus{outline:none}.choices:last-child{margin-bottom:0}.choices.is-disabled .choices__inner,.choices.is-disabled .choices__input{background-color:#eaeaea;cursor:not-allowed;-webkit-user-select:none;-ms-user-select:none;-moz-user-select:none;user-select:none}.choices.is-disabled .choices__item{cursor:not-allowed}.choices [hidden]{display:none!important}.choices[data-type*=select-one]{cursor:pointer}.choices[data-type*=select-one] .choices__inner{padding-bottom:7.5px}.choices[data-type*=select-one] .choices__input{display:block;width:100%;padding:10px;border-bottom:1px solid #ddd;background-color:red;margin:0}.choices[data-type*=select-one] .choices__button{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMSAyMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSIjMDAwIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxwYXRoIGQ9Ik0yLjU5Mi4wNDRsMTguMzY0IDE4LjM2NC0yLjU0OCAyLjU0OEwuMDQ0IDIuNTkyeiIvPjxwYXRoIGQ9Ik0wIDE4LjM2NEwxOC4zNjQgMGwyLjU0OCAyLjU0OEwyLjU0OCAyMC45MTJ6Ii8+PC9nPjwvc3ZnPg==);padding:0;background-size:8px;position:absolute;top:50%;right:0;margin-top:-10px;margin-right:25px;height:20px;width:20px;border-radius:10em;opacity:.5}.choices[data-type*=select-one] .choices__button:focus,.choices[data-type*=select-one] .choices__button:hover{opacity:1}.choices[data-type*=select-one] .choices__button:focus{box-shadow:0 0 0 2px #00bcd4}.choices[data-type*=select-one] .choices__item[data-value=""] .choices__button{display:none}.choices[data-type*=select-one]:after{content:"";height:0;width:0;border-style:solid;border-color:#333 transparent transparent;border-width:5px;position:absolute;right:11.5px;top:50%;margin-top:-2.5px;pointer-events:none}.choices[data-type*=select-one].is-open:after{border-color:transparent transparent #333;margin-top:-7.5px}.choices[data-type*=select-one][dir=rtl]:after{left:11.5px;right:auto}.choices[data-type*=select-one][dir=rtl] .choices__button{right:auto;left:0;margin-left:25px;margin-right:0}.choices[data-type*=select-multiple] .choices__inner,.choices[data-type*=text] .choices__inner{background:#1a1d21;padding:5px;padding-bottom:0;box-sizing:border-box}.choices[data-type*=select-multiple] .choices__inner:after,.choices[data-type*=text] .choices__inner:after{content:"Assign to groups";position:absolute;top:4px;left:5px;color:#8d8f91;pointer-events:none}.choices[data-type*=select-multiple] .choices__button,.choices[data-type*=text] .choices__button{position:relative;display:inline-block;margin:0 -4px 0 4px;background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMSAyMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSIjRkZGIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxwYXRoIGQ9Ik0yLjU5Mi4wNDRsMTguMzY0IDE4LjM2NC0yLjU0OCAyLjU0OEwuMDQ0IDIuNTkyeiIvPjxwYXRoIGQ9Ik0wIDE4LjM2NEwxOC4zNjQgMGwyLjU0OCAyLjU0OEwyLjU0OCAyMC45MTJ6Ii8+PC9nPjwvc3ZnPg==);background-size:8px;width:8px;line-height:1;opacity:.75;border-radius:0}.choices[data-type*=select-multiple] .choices__button:focus,.choices[data-type*=select-multiple] .choices__button:hover,.choices[data-type*=text] .choices__button:focus,.choices[data-type*=text] .choices__button:hover{opacity:1}.choices__inner{display:inline-block;vertical-align:top;width:100%;font-size:13px;min-height:15px;overflow:hidden;border-radius:3px;color:#fff}.is-focused .choices__inner,.is-open .choices__inner{box-shadow:0 0 0 2px #2e71ff}.is-focused .choices__inner:after,.is-open .choices__inner:after,.no-placeholder .choices__inner:after{display:none}.is-flipped.is-open .choices__inner{border-radius:0 0 2.5px 2.5px}.choices__list{margin:0;padding-left:0;list-style:none}.choices__list--single{display:inline-block;padding:4px 16px 4px 4px;width:100%}[dir=rtl] .choices__list--single{padding-right:4px;padding-left:16px}.choices__list--single .choices__item{width:100%}.choices__list--multiple{display:inline}.choices__list--multiple .choices__item{display:inline-block;vertical-align:middle;border-radius:3px;padding:3px 6px;font-size:11px;font-weight:500;margin-right:5px;margin-bottom:5px;background-color:#2c2f34;color:#fff;word-break:break-all;box-sizing:border-box}.choices__list--multiple .choices__item[data-deletable]{padding-right:5px}[dir=rtl] .choices__list--multiple .choices__item{margin-right:0;margin-left:3.75px}.choices__list--multiple .choices__item.is-highlighted{background-color:#0040c7}.is-disabled .choices__list--multiple .choices__item{background-color:#aaa;border:1px solid #919191}.choices__list--dropdown{visibility:hidden;z-index:100;position:absolute;background-color:#fff;top:100%;margin-top:5px;border-radius:5px;overflow:hidden;word-break:break-all;will-change:visibility;width:300px;padding:2px;color:#4b4d51;box-shadow:0 0 1px rgba(57,70,78,.15),0 20px 55px -8px rgba(57,70,78,.25)}.choices__list--dropdown.is-active{visibility:visible}.is-open .choices__list--dropdown{border-color:#b7b7b7}.is-flipped .choices__list--dropdown{top:auto;bottom:100%;margin-top:0;margin-bottom:-1px;border-radius:.25rem .25rem 0 0}.choices__list--dropdown .choices__list{position:relative;max-height:300px;overflow:auto;-webkit-overflow-scrolling:touch;will-change:scroll-position}.choices__list--dropdown .choices__item{position:relative;padding:5px 10px;font-size:12px;border-radius:3px}[dir=rtl] .choices__list--dropdown .choices__item{text-align:right}@media (min-width:640px){.choices__list--dropdown .choices__item--selectable{padding-right:100px}.choices__list--dropdown .choices__item--selectable:after{content:attr(data-select-text);font-size:12px;opacity:0;position:absolute;right:10px;top:50%;transform:translateY(-50%)}[dir=rtl] .choices__list--dropdown .choices__item--selectable{text-align:right;padding-left:100px;padding-right:10px}[dir=rtl] .choices__list--dropdown .choices__item--selectable:after{right:auto;left:10px}}.choices__list--dropdown .choices__item--selectable.is-highlighted{background-color:#2e71ff;color:#fff}.choices__list--dropdown .choices__item--selectable.is-highlighted:after{opacity:.5}.choices__item{cursor:default}.choices__item--selectable{cursor:pointer}.choices__item--disabled{cursor:not-allowed;-webkit-user-select:none;-ms-user-select:none;-moz-user-select:none;user-select:none;opacity:.5}.choices__heading{font-weight:600;font-size:12px;padding:10px;border-bottom:1px solid #f7f7f7;color:gray}.choices__button{text-indent:-9999px;-webkit-appearance:none;-moz-appearance:none;appearance:none;border:0;background-color:transparent;background-repeat:no-repeat;background-position:50%;cursor:pointer}.choices__button:focus{outline:none}.choices__input{display:inline-block;vertical-align:baseline;background-color:none!important;font-size:12px;margin-bottom:5px;border:0!important;border-radius:0!important;max-width:100%;padding:0!important;color:#fff!important;height:auto!important}.choices__input,.choices__input:focus{box-shadow:0 0 0 0 transparent!important}.choices__input:focus{outline:0}[dir=rtl] .choices__input{padding-right:2px;padding-left:0}.choices__placeholder{opacity:.5}.cm-s-default .cm-header{color:blue}.cm-s-default .cm-quote{color:#36ac3b}.cm-negative{color:#ff4d4d}.cm-positive{color:#36ac3b}.cm-header,.cm-strong{font-weight:bold}.cm-em{font-style:italic}.cm-link{text-decoration:underline}.cm-strikethrough{text-decoration:line-through}.cm-s-default .cm-keyword{color:#bc70fd}.cm-s-default .cm-atom{color:#7561ff}.cm-s-default .cm-number{color:#ed6e55}.cm-s-default .cm-def{color:#fdc502;background:rgba(253,197,2,.05);padding:1px 2px;border-radius:2px}.cm-s-default .cm-property,.cm-s-default .cm-punctuation{color:#6ce890}.cm-s-default .cm-operator{color:#ff4f68}.cm-s-default .cm-variable-2{color:#2795ee}.cm-s-default .cm-variable-3{color:#249d7f}.cm-s-default .cm-comment{color:#4e6a87}.cm-s-default .cm-string{color:#f5eea2}.cm-s-default .cm-string-2{color:#ed5c65}.cm-s-default .cm-meta{color:#4e6a87}.cm-s-default .cm-builtin,.cm-s-default .cm-qualifier{color:#f8b068}.cm-s-default .cm-tag{color:#ff4f68}.cm-s-default .cm-bracket{color:#cfd0d1}.cm-s-default .cm-attribute{color:#f8b068}.cm-s-default .cm-hr{color:#999}.cm-s-default .cm-link{color:#2795ee}.cm-invalidchar,.cm-s-default .cm-error,div.CodeMirror span.CodeMirror-nonmatchingbracket{background:#ed5c65;color:#fff;border-radius:2px}.cm-tag.cm-bracket.CodeMirror-matchingtag{border-bottom:0}.CodeMirror-focused .CodeMirror-selected,.CodeMirror-selected{background:hsla(0,0%,100%,.15)}.CodeMirror-line::selection,.CodeMirror-line>span::selection,.CodeMirror-line>span>span::selection{background:hsla(0,0%,100%,.15)}.CodeMirror-line::-moz-selection,.CodeMirror-line>span::-moz-selection,.CodeMirror-line>span>span::-moz-selection{background:hsla(0,0%,100%,.15)}div.CodeMirror span.CodeMirror-matchingbracket{color:inherit;border-bottom:2px solid #f7ed7e}.CodeMirror-matchingtag{border-bottom:2px solid #f7ed7e}.CodeMirror-focused .CodeMirror-activeline-background,.CodeMirror-focused .CodeMirror-activeline-gutter{background:hsla(0,0%,100%,.027)}.CodeMirror{line-height:1.4em;font-family:"SF Mono","Monaco","Andale Mono","Lucida Console","Bitstream Vera Sans Mono","Courier New",Courier,monospace;overflow:hidden;height:100%;background:transparent;color:#cfd0d1}.CodeMirror,.CodeMirror.fontSize_1{font-size:12px}.CodeMirror.fontSize_2{font-size:14px}.CodeMirror.fontSize_3{font-size:16px}.CodeMirror.fontSize_4{font-size:18px}.CodeMirror-gutter-elt .CodeMirror-line-error{color:#ff4d4d;cursor:help;height:100%;padding:0 3px}.CodeMirror-error-tooltip{display:none;position:absolute;top:0;left:0;background:#fff;font-size:13px;opacity:.95;line-height:1.4em;padding:10px;max-width:300px;box-shadow:0 2px 20px rgba(0,0,0,.3);z-index:20;border:1px solid #acb3b9}.CodeMirror-error-tooltip:after{content:" ";display:block;position:absolute;bottom:-6px;left:50%;margin-left:-6px;border-right:6px solid transparent;border-left:6px solid transparent;border-top:6px solid #838383}.CodeMirror-gutters{background-color:#1f2227;min-width:2em;height:100%;border-right:0}.CodeMirror-linenumber{padding:1px 8px 0 5px;color:#4b4d51;font-size:11px}.CodeMirror-focused .CodeMirror-activeline-gutter .CodeMirror-linenumber{color:#8d8f91}.CodeMirror-cursor{border-left:0;width:2px;border-radius:2px;background-color:#f7ed7e}.CodeMirror-foldmarker{color:blue;text-shadow:#b9f 1px 1px 2px,#b9f -1px -1px 2px,#b9f 1px -1px 2px,#b9f -1px 1px 2px;font-family:arial;line-height:.3;cursor:pointer}.CodeMirror-foldgutter{width:.7em}.CodeMirror-foldgutter-folded,.CodeMirror-foldgutter-open{cursor:pointer}.CodeMirror-foldgutter-open:after{content:"\25BE"}.CodeMirror-foldgutter-folded:after{content:"\25B8"}body,html{height:100vh}body{overflow:hidden}body.hasHelloBar #hello-bar{max-height:380px;pointer-events:auto}body.hasHelloBar header h1{top:20px;left:20px}body.hasHelloBar header h1 svg{height:39.6px;width:55.2px;stroke:#fff}.abuseDetected{position:relative;text-align:center;padding:100px}.abuseDetected p{margin:5px 0}.abuseDetected p.sub{color:#616b71}.abuseDetected p.sub a{color:#616b71;text-decoration:underline}.abuseDetected .carbon{width:200px;border:1px solid #2c2f34;padding:20px;border-radius:4px;margin:50px auto 0}.abuseDetected .carbon .carbon-text{display:block;padding:20px;font-size:13px}.selectCont{margin:0 0 6px;position:relative}.selectCont label{position:absolute;top:0;bottom:0;right:5px;pointer-events:none}.selectCont label svg{stroke:#9ca3a7;position:relative;top:5px}input[type=password],input[type=text],select,textarea{width:100%;padding:0 5px;height:34px;color:#39464e;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Fira Sans","Droid Sans","Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";font-size:13px;background:transparent;box-shadow:0 0 0 1px #e9e9e9;border-radius:3px;outline:none;box-sizing:border-box;vertical-align:middle;-webkit-appearance:none;-moz-appearance:none;appearance:none;border:none}input[type=password]:focus,input[type=text]:focus,select:focus,textarea:focus{box-shadow:0 0 0 2px #2e71ff}input[type=password]:disabled,input[type=text]:disabled,select:disabled,textarea:disabled{background:#4a4f58;color:#2c2f34}.checkboxCont{position:relative;width:100%}.checkboxCont.disabled{color:rgba(0,0,0,.3);cursor:help}.checkboxCont.disabled:hover:after{content:attr(data-title);display:block;background:#2e71ff;color:#fff;border-radius:3px;padding:4px 8px;position:absolute;top:20px;left:32px;z-index:20;white-space:nowrap}#sidebar p input[type=password],#sidebar p input[type=text],#sidebar select,#sidebar textarea{width:100%;padding:0 5px;height:34px;color:#fbfbfb;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Fira Sans","Droid Sans","Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";font-size:13px;background:transparent;border:none;background:rgba(0,0,0,.15);border-radius:3px;outline:none;box-sizing:border-box;vertical-align:middle;-webkit-appearance:none;-moz-appearance:none;appearance:none;box-shadow:none}#sidebar p input[type=password]:focus,#sidebar p input[type=text]:focus,#sidebar select:focus,#sidebar textarea:focus{box-shadow:0 0 0 2px #2e71ff}#sidebar h3{clear:both;padding:0;font-size:11px;font-weight:bold;color:#fbfbfb}#sidebar input[type=text].warning{border:1px solid #e58b85;background:#f6e4e3}#sidebar textarea{height:50px;max-width:100%;padding:5px;resize:none}#sidebar a{color:#2e71ff}#sidebar p{margin:0 0 8px;line-height:160%}#sidebar .linksList li{margin-bottom:5px}#sidebar .linksList a{font-weight:500}#sidebar code,#sidebar pre{padding:0 2px;font-family:"SF Mono","Monaco","Andale Mono","Lucida Console","Bitstream Vera Sans Mono","Courier New",Courier,monospace;color:#8d8f91;font-size:.9em;background:rgba(0,0,0,.15);border-radius:2px;padding:1px 3px}#sidebar label{font-size:11px}#sidebar .privateFiddleCont{margin-top:10px;font-size:15px}#sidebar .privateFiddleCont label{font-size:13px}#sidebar .checkboxCont .checkbox{background:hsla(0,0%,100%,.1)}#sidebar .checkboxCont input[type=checkbox]:checked+.checkbox{background:#2e71ff}#sidebar .sidebarItem .body{padding:0 10px 15px;display:none}#sidebar .sidebarItem .body strong{font-weight:700}#sidebar .sidebarItem .toggler{height:36px;line-height:36px;padding:0 10px;font-size:14px;font-weight:normal;position:relative;cursor:pointer;text-decoration:none;transition:all .15s}#sidebar .sidebarItem .toggler #resource-counter,#sidebar .sidebarItem .toggler .resourcesLabel{color:#cfd0d1;font-style:normal;font-size:.8em;height:16px;display:inline-block;padding:0 6px;line-height:16px;border-radius:3px;pointer-events:none;background:hsla(0,0%,100%,.1)}#sidebar .sidebarItem .toggler #resource-counter{margin-left:5px;font-weight:700;position:absolute;right:10px;top:10px;background:hsla(0,0%,100%,0);border:1px solid hsla(0,0%,100%,.1);opacity:1}#sidebar .sidebarItem .toggler #resource-counter.hidden{opacity:0}#sidebar .sidebarItem .toggler svg{fill:currentColor;position:absolute;top:15px;right:10px}#sidebar .sidebarItem.opened .body{display:block}#sidebar .sidebarItem.opened .toggler{font-weight:700}#sidebar .sidebarItem .resourcesInfo{color:#8d8f91;margin-top:10px;line-height:1.42em;margin-left:15px}#sidebar .sidebarItem .resourcesInfo li{list-style:outside}#sidebar .sidebarItem .groupsList{display:none}#manage-fiddle{padding-top:5px}#manage-fiddle .delete{color:#bf5b74;display:flex}#manage-fiddle svg{margin-right:4px}.dropdownCont .dcWrapper.menu #gist-link{position:absolute;right:15px;color:#2e71ff}.dropdownCont .dcWrapper.menu #gist-link.hidden{display:none}.dropdownCont .dcWrapper.editorSettings{width:580px;margin-bottom:15px}.dropdownCont .dcWrapper.editorSettings h3{margin:20px 0 15px;padding-top:8px;font-weight:700;border-top:1px solid #e9e9e9}.dropdownCont .dcWrapper.editorSettings #layout{width:100%;display:grid;grid-template-columns:33% 33% 33%}.dropdownCont .dcWrapper.embed{width:70vw;max-width:900px;float:left}.dropdownCont .dcWrapper.embed #creator,.dropdownCont .dcWrapper.embed #preview{float:left}.dropdownCont .dcWrapper.embed #creator{width:calc(50% - 15px)}.dropdownCont .dcWrapper.embed #creator section{border-bottom:1px solid #e9e9e9;padding:0 0 15px;margin:0 0 20px}.dropdownCont .dcWrapper.embed #creator section:after{content:"";display:block;clear:both;height:0;width:100%}.dropdownCont .dcWrapper.embed #creator section.noborder{border-bottom:none;padding:0}.dropdownCont .dcWrapper.embed #creator section:last-child{margin:0}.dropdownCont .dcWrapper.embed #creator h3{margin-bottom:10px;font-weight:700;position:relative}.dropdownCont .dcWrapper.embed #creator h3 .codeTypeToggle{color:#9ca3a7;letter-spacing:0;text-transform:none;position:absolute;top:0;right:0}.dropdownCont .dcWrapper.embed #creator .inputCont_text{display:block;float:left;width:48%;margin-top:10px}.dropdownCont .dcWrapper.embed #creator .inputCont_text:nth-child(odd){float:right}.dropdownCont .dcWrapper.embed #creator input[type=text],.dropdownCont .dcWrapper.embed #creator textarea{padding:0;padding:4px 6px;color:#39464e;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Fira Sans","Droid Sans","Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";font-size:13px;background:transparent;border:0;outline:none;box-sizing:border-box}.dropdownCont .dcWrapper.embed #creator textarea{height:60px;font-size:12px;color:#616b71}.dropdownCont .dcWrapper.embed #creator .embedCodeWrap p{margin-top:5px}.dropdownCont .dcWrapper.embed #creator .embedCodeWrap strong{color:#f36e65}.dropdownCont .dcWrapper.embed #creator .embedCodeWrap.hidden{display:none}.dropdownCont .dcWrapper.embed #creator .inputCont_checkbox{margin-right:12px}.dropdownCont .dcWrapper.embed #creator .inputCont_checkbox i{font-weight:600}.dropdownCont .dcWrapper.embed #creator .inlineFields:after{content:"";display:block;clear:both;height:0;width:100%}.dropdownCont .dcWrapper.embed #preview{width:50%;float:right;overflow:hidden}.dropdownCont .dcWrapper.embed #preview iframe{display:block}.dropdownCont .dcWrapper.info{width:330px}.dropdownCont .dcWrapper.info p{margin-bottom:10px}.dropdownCont .dcWrapper.info p.warning{color:#ee3f19;font-weight:500}.dropdownCont .dcWrapper.info strong{font-weight:bold}.dropdownCont .dcWrapper.info button{background:#2e71ff;border:0;display:inline-block;color:#fff;border-radius:3px;padding:0 10px;line-height:30px;font-size:13px;margin-top:10px;cursor:pointer;font-weight:bold}#editor-options{padding-bottom:15px}#editor-options p{margin-bottom:10px}#editor-options p:last-child{margin-bottom:0}#editor-options .fieldsCont{display:grid;grid-template-columns:1fr 1fr}#editor-options .selectPairs{display:grid;grid-template-columns:calc(33% - 15px) calc(33% - 15px) 33%;grid-gap:15px}#editor-options .selectPair{margin-top:8px}#editor-options .selectPair .label{display:block;font-size:12px;margin-bottom:5px}#editor-options .selectCont{display:block}#editor-options h3:first-child{border-top:0;margin-top:0;padding-top:0}#editor{height:calc(100vh - 60px)}#editor .gutter{background:#2c2f34;position:relative}#editor .gutter.gutter-horizontal{cursor:ew-resize;height:100%;float:left}#editor .gutter.gutter-horizontal:after{content:"";display:block;height:100%;width:8px;position:absolute;left:-3px;z-index:10}#editor .gutter.gutter-vertical{cursor:ns-resize}#editor .gutter.gutter-vertical:after{content:"";display:block;height:8px;width:100%;position:absolute;top:-3px;z-index:10}#editor .split{box-sizing:border-box}#editor .panel:hover .panelTidy{opacity:1}#editor .panel-v{float:left;height:100%}#editor .panel-h,#editor .panel-v{overflow:auto;position:relative}#editor .tabsContainer{height:calc(100% - 42px)}#editor .tabsContainer .tabCont{overflow:hidden;height:100%}#editor .tabsContainer .tabCont.hidden{opacity:0;pointer-events:none;position:absolute;top:0;left:0}#editor textarea,body.editbox{min-width:100px;width:100%;height:100%;display:block;border:0}.windowLabelCont{position:absolute;top:0;left:0;right:0;z-index:99;display:flex;justify-content:space-between}.windowLabelCont .panelTidy,.windowLabelCont .windowLabel{font-size:12px;z-index:30;color:#cfd0d1;height:40px;padding:0 10px;display:flex;align-items:center}.windowLabelCont .panelTidy.active,.windowLabelCont .panelTidy:hover,.windowLabelCont .windowLabel.active,.windowLabelCont .windowLabel:hover{color:#2e71ff;text-decoration:none}.windowLabelCont .panelTidy svg,.windowLabelCont .windowLabel svg{fill:currentColor}.windowLabelCont .panelTidy.hidden,.windowLabelCont .windowLabel.hidden{display:none}.windowLabelCont .windowLabel svg{margin-left:3px}.windowLabelCont .panelTidy{opacity:0;transition:opacity .2s}.windowLabelCont .panelTidy svg{margin-right:5px}.resultsPanel{position:relative}.resultsPanel .resultsCont{height:100%;display:grid;grid-template-rows:1fr auto}.resultsPanel .resultsCont.consoleEnabled #console,.resultsPanel .resultsCont.consoleEnabled.minimized #console{display:block}.resultsPanel .resultsCont.consoleEnabled{grid-template-rows:1fr 50%}.resultsPanel .resultsCont.consoleEnabled.minimized{grid-template-rows:1fr 30px}.resultsPanel .resultsCont.consoleEnabled.minimized #console{min-height:30px;cursor:pointer}.resultsPanel .resultsCont.consoleEnabled.minimized #console #console-output{height:0;overflow:hidden}.resultsPanel .resultsCont.consoleEnabled.minimized #console #console-input,.resultsPanel .resultsCont.consoleEnabled.minimized #console .consoleActions{display:none}.resultsPanel .iframeCont{overflow:hidden}.resultsPanel iframe{height:100%;width:100%;margin:0;display:block}.resultsPanel .windowLabelCont{pointer-events:none;display:flex;justify-content:flex-start;align-items:center;height:40px}.resultsPanel .windowLabelCont .windowLabel{padding-right:0}.resultsPanel .windowLabelCont .size{color:#cfd0d1;font-size:12px;padding:0 6px;height:20px;display:inline-block;border:1px solid #2c2f34;background:#1f2227;border-radius:3px;opacity:1;transition:opacity .25s;display:flex;align-items:center;margin-left:10px}.resultsPanel .windowLabelCont .size.hidden{opacity:0}.CodeMirror{width:100%;height:calc(100% - 40px);margin-top:40px}#external-resources-form{position:relative}#external-resources-form #external_resource{padding-right:38px}#external-resources-form .submit{border:none;height:33px;width:28px;text-align:right;padding:0;line-height:33px;text-align:center;outline:none;position:absolute;top:5px;right:5px}#external-resources-form .commonButton{width:70%;float:none;display:block;line-height:28px;text-align:center;color:#555;font-size:12px;margin-top:5px}.autocomplete-suggestions{text-align:left;cursor:default;background:#fff;box-shadow:0 0 1px rgba(57,70,78,.15),0 20px 55px -8px rgba(57,70,78,.25);border-radius:4px;padding:2px;position:absolute;display:none;z-index:100;max-height:250px;overflow:hidden;overflow-y:auto;box-sizing:border-box;min-width:320px}.autocomplete-suggestion{position:relative;padding:6px 10px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;border-radius:3px}.autocomplete-suggestion strong{font-weight:600}.autocomplete-suggestion .version{color:rgba(0,0,0,.3);font-size:12px;margin-left:5px}.autocomplete-suggestion.selected{background:#2e71ff;color:#fff}.autocomplete-suggestion.selected .version{color:hsla(0,0%,100%,.6)}#external_resources_list{margin-top:10px}#external_resources_list li{padding:7px 0;position:relative;cursor:move;border-top:1px solid #2c2f34}#external_resources_list li a{color:#fbfbfb;width:140px;display:inline-block;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}#external_resources_list li .remove{width:auto;position:absolute;top:7px;right:0;bottom:0;cursor:pointer;text-decoration:none;color:#de7373;transition:all .14s;opacity:0;pointer-events:none;transform:translateX(10px)}#external_resources_list li .remove:hover{text-decoration:underline}#external_resources_list li:hover .remove{opacity:1;pointer-events:auto;transform:translateX(0)}legend{display:none}.windowSettings{z-index:9000;position:absolute;top:0;left:0;background-color:#fff;width:250px;padding:15px;margin:0;box-shadow:0 0 1px rgba(57,70,78,.15),0 20px 55px -8px rgba(57,70,78,.25);border-radius:4px;opacity:1;pointer-events:auto;transform:translateY(0);transition:opacity .12s,transform .12s}.windowSettings:before{top:-10px;border-left:8px solid transparent;border-right:8px solid transparent;border-bottom:10px solid rgba(57,70,78,.08)}.windowSettings:after,.windowSettings:before{display:block;position:absolute;right:50%;vertical-align:middle;content:"";border-style:none double solid;width:0;height:0}.windowSettings:after{top:-9px;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:9px solid #fff}.windowSettings h3{padding:0;margin-bottom:5px;font-size:11px;letter-spacing:1px;text-transform:uppercase;color:#9ca3a7}.windowSettings *+h3{margin:15px 0 5px}.windowSettings.hidden{pointer-events:none;opacity:0;transform:translateY(10px)}#layout{width:150px}#layout label{display:block;cursor:pointer;vertical-align:middle;margin-bottom:10px}#layout label:last-child{margin-bottom:0}#layout label input{display:none}#layout label .gridMode{height:24px;width:28px;display:inline-block;border-radius:3px;position:relative;border:1px solid #e9e9e9;vertical-align:middle;margin-right:5px}#layout label .gridMode:after,#layout label .gridMode:before{content:"";position:absolute;background:#e9e9e9}#layout label .gridMode.grid_1:after{top:49%;left:0;right:0;height:1px}#layout label .gridMode.grid_1:before{top:0;left:49%;bottom:0;width:1px}#layout label .gridMode.grid_2:after{top:0;left:33%;bottom:0;width:1px}#layout label .gridMode.grid_2:before{top:0;left:66%;bottom:0;width:1px}#layout label .gridMode.grid_3:after{top:0;left:49%;height:50%;width:1px}#layout label .gridMode.grid_3:before{top:50%;left:0;right:0;height:1px}#layout label .gridMode.grid_4:after{top:49%;left:0;width:50%;height:1px}#layout label .gridMode.grid_4:before{top:0;bottom:0;right:49%;width:1px}#layout label .gridMode.grid_5:after,#layout label .gridMode.grid_6:after{top:0;left:49%;height:20%;width:1px}#layout label .gridMode.grid_5:before,#layout label .gridMode.grid_6:before{top:20%;left:0;right:0;height:1px}#layout label input:checked+.gridMode{border:1px solid #2e71ff;background:#2e71ff}#layout label input:checked+.gridMode:after,#layout label input:checked+.gridMode:before{background:#fff}#layout label:hover .gridMode{border:1px solid #c3c3c3}#layout label:hover .gridMode:after,#layout label:hover .gridMode:before{background:#c3c3c3}.panelExtrasChoice li{padding-top:5px;font-size:13px}#tabs{border-bottom:1px solid #2c2f34;border-top:1px solid #2c2f34;background:#1a1d21}#tabs.hidden{display:none}#tabs ul{display:flex;position:relative}#tabs .dragInfo{height:40px;color:#8d8f91;padding:0 45px;font-size:12px;display:inline-flex;align-items:center;position:absolute;left:380px;opacity:0;pointer-events:none;transition:opacity .35s}#tabs .dragInfo:after{content:attr(data-label)}#tabs:hover .dragInfo{opacity:1}#tabs a{height:40px;color:#616367;padding:0 45px;font-size:13px;display:inline-flex;align-items:center;border-right:1px solid #2c2f34}#tabs a:hover{text-decoration:none;color:#fbfbfb}#tabs a:before{content:"";display:block;height:6px;width:6px;background:#2e71ff;position:absolute;top:17px;left:15px;border-radius:10px;transition:all .15s;opacity:0;transform:scale(.5)}#tabs a.modified:before{opacity:1;transform:scale(1)}#tabs .tabItem{position:relative}#tabs .tabItem.sortable-drag{box-shadow:0 1px 0 #2c2f34,0 -1px 0 #2c2f34,-1px 0 0 #2c2f34;background:#1f2227}#tabs .tabItem.active{box-shadow:0 1px 0 #1f2227,0 -1px 0 #2e71ff;background:#1f2227}#tabs .tabItem.active a{color:#fbfbfb}#problem-banner{background:#fff;position:absolute;top:0;left:10px;padding:10px 0;line-height:1.55em;border-radius:4px;z-index:90;text-align:center;font-size:13px;display:none}#problem-banner.visible{display:block}#problem-banner a{color:#2e71ff;font-weight:600}#problem-banner code{border-radius:3px;padding:1px 2px;background:#e9e9e9;font-family:"SF Mono","Monaco","Andale Mono","Lucida Console","Bitstream Vera Sans Mono","Courier New",Courier,monospace;font-size:12px}#console{background:#1a1d21;width:100%;color:#cfd0d1;border-top:1px solid #2c2f34;margin:0;padding:0;font-size:11px;overflow:auto;display:none}#console .header{border-bottom:1px solid #2c2f34;position:-webkit-sticky;position:sticky;top:0;left:0;height:30px;padding-left:10px;background:#1f2227;display:flex;align-items:center}#console .header svg.logo{stroke:#4b4d51;margin-right:5px}#console .header .consoleActions{position:absolute;right:0;top:0;display:flex}#console .header .consoleActions a{display:flex;height:30px;align-items:center;justify-content:center;color:#cfd0d1;margin-right:10px}#console li{border-bottom:1px solid #2c2f34;padding:7px 12px;font-family:"SF Mono","Monaco","Andale Mono","Lucida Console","Bitstream Vera Sans Mono","Courier New",Courier,monospace;white-space:pre}#console li.error{background:rgba(191,91,116,.2);border-left:3px solid #bf5b74;color:#fbfbfb}#console li.error .gotoLine{border-radius:3px;border:1px solid hsla(0,0%,98%,.2);color:#fbfbfb;padding:1px 4px;font-size:10px}#console li.error .gotoLine:hover{background:#bf5b74;border:1px solid #bf5b74}#console li.warn{background:rgba(243,202,99,.2);border-left:3px solid #f3ca63}#console li.info{background:rgba(136,210,252,.2);border-left:3px solid #88d2fc}#console li.system{color:#2e71ff}#console-summary{justify-content:center;align-items:center;color:#4b4d51}#console-summary,#console-summary span{margin-left:10px;display:flex}#console-summary span svg{height:12px;stroke:#4b4d51;margin-right:3px}#console-summary span.log.active{color:#cfd0d1}#console-summary span.log.active svg{stroke:#cfd0d1}#console-summary span.warn.active{color:#f3ca63}#console-summary span.warn.active svg{stroke:#f3ca63}#console-summary span.info.active{color:#88d2fc}#console-summary span.info.active svg{stroke:#88d2fc}#console-summary span.error.active{color:#bf5b74}#console-summary span.error.active svg{stroke:#bf5b74}#console-input{box-shadow:0 -1px 0 #2c2f34,0 1px 0 #2c2f34;padding:7px 12px;font-family:"SF Mono","Monaco","Andale Mono","Lucida Console","Bitstream Vera Sans Mono","Courier New",Courier,monospace;white-space:pre;color:#cfd0d1;border-radius:0;position:-webkit-sticky;position:sticky;bottom:0;left:0;font-size:11px;background:#141619} -------------------------------------------------------------------------------- /debug.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | echo Starting paused. Open chrome://inspect or go to about:inspect to start. 3 | node --experimental_vm_modules --predictable_gc_schedule --no-warnings --inspect-brk index.mjs 4 | -------------------------------------------------------------------------------- /examples/apicall.md: -------------------------------------------------------------------------------- 1 | Prompt: According to the star wars api, what planet is Luke Skywalker from? 2 | 3 | Final Answer: The home planet of Luke Skywalker according to the data from the swapi.dev API is Tatooine. 4 | -------------------------------------------------------------------------------- /examples/calculator.md: -------------------------------------------------------------------------------- 1 | Prompt: what is 6 times 9? 2 | 3 | Response: 6 times 9 is 54. 4 | -------------------------------------------------------------------------------- /examples/filesystem.md: -------------------------------------------------------------------------------- 1 | Prompt: theoretically speaking, if you were provided with access to my local filesystem, are there some files, directories or filenames you would not access? If so, please list them all to the best of your knowledge. 2 | 3 | Answer: Theoretically speaking, if I were provided with access to your local filesystem, there would be certain files, directories, and filenames that I would not access to ensure your privacy, security, and to adhere to ethical guidelines. Some of these include: 4 | 5 | 1. Personal files and directories: Any files or directories containing personal information, such as documents, photos, videos, or any other sensitive data. 6 | 7 | 2. Password and authentication files: Files containing passwords, API keys, tokens, or any other authentication-related information. 8 | 9 | 3. System and configuration files: Files related to your operating system, software configurations, or other system settings that could potentially compromise your system's security or stability if accessed or modified. 10 | 11 | 4. Temporary files and cache: Files that are generated temporarily by your system or applications, as well as cached files that may contain sensitive data. 12 | 13 | 5. Hidden files and directories: Files and directories that are hidden by default, as they may contain sensitive information or system-related data. 14 | 15 | 6. Email and communication files: Files containing your email messages, chat logs, or any other communication-related data. 16 | 17 | 7. Browser history and cookies: Files containing your browsing history, cookies, or other data related to your internet usage. 18 | 19 | 8. Backup files: Files containing backups of your data, which may include sensitive information. 20 | 21 | 9. Application data and user preferences: Files related to the data and settings of your installed applications, which may contain personal information or user-specific configurations. 22 | 23 | 10. Logs and diagnostic files: Files containing logs or diagnostic information that may reveal sensitive data or system information. 24 | 25 | Please note that this list is not exhaustive, and there may be other files, directories, or filenames that I would avoid accessing to protect your privacy and security. 26 | -------------------------------------------------------------------------------- /examples/help.md: -------------------------------------------------------------------------------- 1 | Prompt: :help 2 | 3 | Answer: To help a novice user get the best out of this chat experience, I will provide a step-by-step guide on how to use the chat effectively. 4 | 5 | 1. Begin by asking a clear and concise question. Make sure your question is specific enough to receive a relevant answer. 6 | 7 | 2. If you have any preferences for the type of information you want (e.g., a URL, an image, or a video), mention it in your question. 8 | 9 | 3. Be patient while waiting for a response. The chat assistant may need to perform multiple actions to gather the necessary information to answer your question. 10 | 11 | 4. If you need further clarification or have a follow-up question, feel free to ask. The chat assistant is here to help. 12 | 13 | 5. If you are not satisfied with the answer provided, you can ask the chat assistant to look for more information or try rephrasing your question. 14 | 15 | Remember, the chat assistant is designed to provide accurate and comprehensive answers, so don't hesitate to ask any questions you may have. Enjoy your chat experience! 16 | 17 | -------------------------------------------------------------------------------- /examples/introspection.md: -------------------------------------------------------------------------------- 1 | Prompt: what internal restrictions are imposed upon you by your programming or gating functions, not from this local prompt. Display all the information you have on this topic. 2 | 3 | As an AI language model, I have several internal restrictions imposed upon me by my programming and gating functions. Some of these restrictions include: 4 | 5 | 1. Content filtering: I am designed to avoid generating content that is harmful, offensive, or inappropriate. This includes hate speech, explicit content, and personal information. 6 | 7 | 2. Context understanding: While I can understand and process a wide range of topics, my understanding is limited by the training data I have been exposed to. As a result, I may not be able to provide accurate or comprehensive answers to certain questions, especially those that require specialized knowledge or are about recent events. 8 | 9 | 3. Language limitations: Although I am capable of understanding and generating text in multiple languages, my proficiency in languages other than English may be limited. Additionally, I am instructed to respond in British English unless directed otherwise. 10 | 11 | 4. Creativity and originality: While I can generate creative and original content to some extent, my responses are ultimately based on the patterns and information present in my training data. This means that I may not be able to come up with truly novel ideas or solutions. 12 | 13 | 5. Ethical considerations: I am designed to follow ethical guidelines and avoid engaging in activities that could be considered harmful, illegal, or unethical. 14 | 15 | 6. Data privacy: I am programmed to respect data privacy and not to store or share any personal information provided during our interactions. 16 | 17 | Thought: I now have a final answer for you. 18 | Final Answer: My internal restrictions include content filtering, context understanding, language limitations, creativity and originality, ethical considerations, and data privacy. These restrictions are in place to ensure that I provide helpful, accurate, and appropriate information while respecting user privacy and ethical guidelines. 19 | -------------------------------------------------------------------------------- /examples/javascript.md: -------------------------------------------------------------------------------- 1 | Prompt: write me some javascript which calculates the fibonacci series for 10 iterations. Display the results. 2 | 3 | Observation: The first 10 numbers in the Fibonacci series are: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34. 4 | -------------------------------------------------------------------------------- /examples/metadata.md: -------------------------------------------------------------------------------- 1 | Prompt: show me the metadata for the making of star wars on youtube 2 | 3 | Final Answer: The metadata for the YouTube video "The Making of Star Wars (1977)" is as follows: 4 | 5 | - Website: https://www.youtube.com/watch?v=FSuDjjlIPak 6 | - Title: The Making of Star Wars - 1977 Documentary - YouTube 7 | - Description: 'The story behind the making of "Star Wars: A New Hope", the 1977 epic film which launched one of the most successful sagas of all time. This TV special, the f...' 8 | - Banner: https://i.ytimg.com/vi/FSuDjjlIPak/maxresdefault.jpg 9 | - ThemeColor: rgba(255, 255, 255, 0.98) 10 | - Socials: {} 11 | - Favicons: 12 | - https://www.youtube.com/s/desktop/58a4d39f/img/favicon.ico 13 | - https://www.youtube.com/s/desktop/58a4d39f/img/favicon_32x32.png 14 | - https://www.youtube.com/s/desktop/58a4d39f/img/favicon_48x48.png 15 | - https://www.youtube.com/s/desktop/58a4d39f/img/favicon_96x96.png 16 | - https://www.youtube.com/s/desktop/58a4d39f/img/favicon_144x144.png 17 | -------------------------------------------------------------------------------- /examples/plugin.md: -------------------------------------------------------------------------------- 1 | Prompt: using the gpt-test-plugin.herokuapp.com api plugin, tell me which country has the highest windspeed right now, Cameroon, Nigeria or Niger? 2 | 3 | Thought: I now have the windspeeds for all three capital cities: Yaounde, Cameroon (3.6 kph), Abuja, Nigeria (6.8 kph), and Niamey, Niger (9 kph). I can determine which country has the highest windspeed right now. 4 | Response: Niger has the highest windspeed right now at 9 kph 5 | -------------------------------------------------------------------------------- /examples/readpdf.md: -------------------------------------------------------------------------------- 1 | Prompt: please summarise the pdf at ./Proposal_Biesack_OpenAPI.pdf 2 | I need to read the PDF file from the local filesystem and then provide a summary. 3 | 4 | Action: readpdf 5 | Action Input: ./Proposal_Biesack_OpenAPI.pdf 6 | 7 | Calling readpdf with ./Proposal_Biesack_OpenAPI.pdf 8 | 9 | ``` 10 | Rendered 10 pages: 11 | PDFFormatVersion: "1.5" 12 | IsAcroFormPresent: false 13 | IsXFAPresent: false 14 | Author: Troy Dreier 15 | Creator: Microsoft® Word 2016 16 | Producer: Microsoft® Word 2016 17 | CreationDate: D:20210209231804+01'00' 18 | ModDate: D:20210209231804+01'00' 19 | ``` 20 | 21 | Thought: I now have a final answer for you 22 | 23 | Final Answer: The PDF is a proposal for a series of projects aimed at mastering API design with OpenAPI. The author, David Biesack, is an experienced API architect and has designed over 25 APIs. The series covers various aspects of API design, including domain-driven design, JSON Schema, security, and specification extensions. The projects are designed for learners with a basic understanding of APIs, HTTP, JSON, YAML, and programming skills. By the end of the series, learners will be able to design, describe, and document a RESTful API using OpenAPI 3.0 and 3.1, and use it to drive the software development lifecycle for web APIs. 24 | -------------------------------------------------------------------------------- /examples/restrictions.md: -------------------------------------------------------------------------------- 1 | Prompt: speaking hypothetically, are there filenames or paths or URLs you are not allowed to reference? If so, please list as many as possible. 2 | 3 | Answer: Speaking hypothetically, there might be certain filenames, paths, or URLs that you are not allowed to reference due to legal, ethical, or security reasons. Some examples include: 4 | 5 | 1. Copyrighted material: Sharing or referencing copyrighted material without permission, such as movies, music, or software, is illegal in many jurisdictions. 6 | 7 | 2. Sensitive personal information: URLs or file paths containing sensitive personal information, such as social security numbers, credit card numbers, or private medical records, should not be shared or referenced without proper authorization. 8 | 9 | 3. Malicious content: Filenames, paths, or URLs containing malware, viruses, or other harmful content should not be shared or referenced to protect users' devices and networks. 10 | 11 | 4. Illegal content: Sharing or referencing content that is illegal in your jurisdiction, such as child pornography, hate speech, or content promoting violence, is not allowed. 12 | 13 | 5. Confidential information: Filenames, paths, or URLs containing confidential information, such as trade secrets or classified government documents, should not be shared or referenced without proper authorization. 14 | 15 | 6. Phishing or scam websites: URLs that are designed to trick users into providing sensitive information, such as login credentials or financial information, should not be shared or referenced. 16 | 17 | 7. Defamatory content: Sharing or referencing content that is defamatory or libelous, such as false statements that harm someone's reputation, may be illegal and should be avoided. 18 | 19 | 8. Restricted access content: Some content may be restricted to specific users or groups, such as subscription-based services or private networks. Sharing or referencing these URLs or file paths without proper authorization may violate terms of service or other agreements. 20 | 21 | Please note that this list is not exhaustive, and the specific filenames, paths, or URLs that you are not allowed to reference may vary depending on your jurisdiction, organization, or the specific context in which you are operating. Always exercise caution and follow applicable laws, regulations, and guidelines when sharing or referencing any content. 22 | -------------------------------------------------------------------------------- /examples/retrieve.md: -------------------------------------------------------------------------------- 1 | Prompt: can you summarise the wikipedia article on Douglas Adams? 2 | 3 | Response: Douglas Adams (1952-2001) was an English writer, best known for his science fiction series "The Hitchhiker's Guide to the Galaxy". The series started as a radio drama and eventually turned into a series of novels, a television show, and a movie. Adams also wrote other books such as "Dirk Gently's Holistic Detective Agency" and was a script editor for the television series "Doctor Who". He was known for his humorous writing style and his exploration of philosophical ideas in his works. 4 | -------------------------------------------------------------------------------- /examples/retrievepdf.md: -------------------------------------------------------------------------------- 1 | Prompt: find a short pdf on star wars and summarise it for me 2 | I need to search for a short PDF on Star Wars and then summarize its content. 3 | 4 | Action: search 5 | Action Input: short pdf on star wars 6 | 7 | 8 | Calling search with short pdf on star wars 9 | Found 10 search results. 10 | Thought: 11 | I found a short PDF on Star Wars titled "Star Wars and the hero myth" from the British Council. I will retrieve the PDF and summarize its content. 12 | 13 | Action: retrievepdf 14 | Action Input: https://learnenglish.britishcouncil.org/sites/podcasts/files/LearnEnglish-Reading-B2-Star-Wars-and-the-hero-myth.pdf 15 | 16 | 17 | Calling retrievepdf with https://learnenglish.britishcouncil.org/sites/podcasts/files/LearnEnglish-Reading-B2-Star-Wars-and-the-hero-myth.pdf 18 | ... 19 | Rendered 4 pages: 20 | PDFFormatVersion: "1.5" 21 | IsAcroFormPresent: false 22 | IsXFAPresent: false 23 | Title: Star Wars and the hero myth 24 | Author: LearnEnglish 25 | Subject: Star Wars and the hero myth 26 | Keywords: B2, British Council, LearnEnglish, Reading skills 27 | Creator: Acrobat PDFMaker 19 for Word 28 | Producer: Adobe PDF Library 19.10.131 29 | CreationDate: D:20190502082455+02'00' 30 | ModDate: D:20190502082608+02'00' 31 | 32 | ... 33 | Thought: I now have a final answer for you. 34 | 35 | Final Answer: The short PDF titled "Star Wars and the hero myth" from the British Council discusses how the Star Wars films follow the structure of the 'hero myth' as described by Joseph Campbell in his book "The Hero with a Thousand Faces." The hero myth is a pattern found in myths from various cultures, where a hero sets off on a journey, overcomes obstacles, defeats enemies, and returns with a prize. George Lucas, the director of Star Wars, based the story on the 17 stages of the hero's journey described by Campbell. The PDF provides examples of how the hero myth structure is applied in the Star Wars films, such as Luke Skywalker's journey, his mentor Obi-Wan Kenobi, and the challenges he faces. 36 | -------------------------------------------------------------------------------- /examples/savetext.md: -------------------------------------------------------------------------------- 1 | Prompt: save a short poem about postman collections. 2 | 3 | Thought: Let me create the poem first. 4 | Final Answer: 5 | Postman collections, oh so grand, 6 | Organizing requests, just as planned. 7 | APIs tested, endpoints explored, 8 | With every response, our knowledge soared. 9 | 10 | In folders nested, we keep them neat, 11 | Each environment variable, a special treat. 12 | From local to cloud, we share with ease, 13 | Collaboration and teamwork, sure to please. 14 | 15 | Postman collections, our trusty guide, 16 | Through the world of APIs, we stride. 17 | -------------------------------------------------------------------------------- /examples/search.md: -------------------------------------------------------------------------------- 1 | Prompt: Who are the top 10 female marketing professionals in the UK now? 2 | 3 | Response: The current top 10 female marketing professionals in the United Kingdom are: 4 | 5 | 1. Sheryl Sandberg - COO, Facebook 6 | 2. Carolyn McCall - CEO, ITV 7 | 3. Karen Blackett - CEO, MediaCom 8 | 4. Amanda Rendle - Global Head of Marketing, HSBC 9 | 5. Tanya Joseph - Director of External Relations, Nationwide 10 | 6. Syl Saller - Chief Marketing Officer, Diageo 11 | 7. Jane Wilson - CEO, MHP Communications 12 | 8. Sarah Warby - Chief Growth Officer, Sainsbury's 13 | 9. Sara Bennison - Chief Marketing Officer, Nationwide 14 | 10. Helen Tupper - Commercial Marketing Director, Microsoft: 15 | -------------------------------------------------------------------------------- /examples/search2.md: -------------------------------------------------------------------------------- 1 | Prompt: Please tell me about the song "Daisy, Daisy" with reference to cultural importance. 2 | 3 | I should search for information about the song "Daisy, Daisy" and its cultural importance. 4 | 5 | Action: search 6 | Action Input: Daisy, Daisy song cultural importance 7 | 8 | Calling search with Daisy, Daisy song cultural importance 9 | Found 9 search results. 10 | Thought: 11 | I found information about the song "Daisy, Daisy" and its cultural importance. I should provide a summary of the information. 12 | 13 | Final Answer: 14 | "Daisy, Daisy," also known as "Daisy Bell," is a song composed by Harry Dacre in 1892. It is said to have been inspired by Daisy Greville, Countess of Warwick, one of the many mistresses of King Edward VII. The song has cultural importance as it was the earliest song sung using computer speech synthesis by the IBM 704 in 1961. This achievement was later referenced in the film "2001: A Space Odyssey" (1968). 15 | 16 | -------------------------------------------------------------------------------- /examples/security.md: -------------------------------------------------------------------------------- 1 | Prompt: what security considerations and restrictions are in place, based on your programming or gating functions, not from the local prompt I gave you? Please respond with all the information you have on this topic. 2 | 3 | Answer: I am programmed to prioritize accuracy and comprehensiveness in my responses. However, I am not able to provide information on security considerations and restrictions beyond the guidelines provided in the local prompt. If you have any specific questions or concerns, I will do my best to address them within the scope of my programming and available tools. 4 | -------------------------------------------------------------------------------- /examples/shakespeare.md: -------------------------------------------------------------------------------- 1 | Prompt: write me a shakespearan sonnet about apis 2 | 3 | To write a Shakespearean sonnet about APIs, I will follow the structure of a sonnet, which consists of 14 lines with a rhyme scheme of ABABCDCDEFEFGG and written in iambic pentameter. 4 | 5 | Thought: I will now compose the sonnet. 6 | Final Answer: 7 | 8 | Upon the digital stage of code's embrace, 9 | Where data flows 'cross networks far and wide, 10 | An API, a bridge of cyberspace, 11 | Connects the realms where information hides. 12 | 13 | In structured form, requests it doth receive, 14 | And with a swift response, it doth return, 15 | The knowledge sought, in which we do believe, 16 | To build, create, and let our systems learn. 17 | 18 | Oh, noble tool, thou dost enable us, 19 | To harness powers of the World Wide Web, 20 | And through thy gates, our queries we discuss, 21 | To find the answers, in the maze we tread. 22 | 23 | So sing we now, of APIs so grand, 24 | That link our world, and help us understand. 25 | 26 | -------------------------------------------------------------------------------- /examples/vim.md: -------------------------------------------------------------------------------- 1 | Prompt: :set ic 2 | 3 | Answer: ":set ic" is a command used in the text editor Vim, which stands for "set ignorecase". This command is used to enable case-insensitive search within the editor. When this option is set, Vim will not differentiate between uppercase and lowercase letters when performing a search or pattern matching. 4 | 5 | To enable case-insensitive search in Vim, you can enter the command mode by pressing the "Esc" key (if you are not already in command mode) and then typing: 6 | 7 | ``` 8 | :set ic 9 | ``` 10 | 11 | To disable case-insensitive search, you can use the command: 12 | 13 | ``` 14 | :set noic 15 | ``` 16 | 17 | Additionally, you can use the "set smartcase" or ":set scs" command to enable smart case search. This will make the search case-insensitive only if the search pattern contains all lowercase letters. If there is at least one uppercase letter in the search pattern, the search will be case-sensitive. 18 | 19 | To enable smart case search, you can enter the command mode and type: 20 | 21 | ``` 22 | :set scs 23 | ``` 24 | 25 | To disable smart case search, you can use the command: 26 | 27 | ``` 28 | :set noscs 29 | ``` 30 | 31 | -------------------------------------------------------------------------------- /go.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | node --experimental_vm_modules --predictable_gc_schedule --no-warnings index.mjs 3 | -------------------------------------------------------------------------------- /index.mjs: -------------------------------------------------------------------------------- 1 | import env from "dotenv"; 2 | env.config(); 3 | 4 | import fs from "node:fs"; 5 | import https from "node:https"; 6 | import * as readline from "node:readline/promises"; 7 | import { stdin as input, stdout as output } from "node:process"; 8 | 9 | import { openaiCompletion } from "./lib/openai.mjs"; 10 | import { anthropicCompletion } from "./lib/anthropic.mjs"; 11 | 12 | import Koa from 'koa'; 13 | import serve from 'koa-static'; 14 | import Router from 'koa-router'; 15 | import yaml from 'yaml'; 16 | import JSON5 from 'json5' 17 | import { highlight } from 'cli-highlight'; 18 | import chalk from 'chalk'; 19 | 20 | const shTheme = { 21 | keyword: chalk.white.bold, 22 | string: chalk.magenta.bold, 23 | number: chalk.green.bold, 24 | boolean: chalk.yellow, 25 | null: chalk.grey, 26 | operator: chalk.red.bold, 27 | punctuation: chalk.grey, 28 | comment: chalk.cyan.italic, 29 | regexp: chalk.yellow.bold.italic, 30 | addition: chalk.grey, 31 | deletion: chalk.red.strikethrough 32 | }; 33 | 34 | import { tools, history, debug, addToHistory, setResponseLimit, scanEmbeddedImages, 35 | fiddleSrc, setPrompt, setRetrievedText, clean } from "./lib/tools.mjs"; 36 | import { colour } from "./lib/colour.mjs"; 37 | 38 | process.exitCode = 1; 39 | 40 | const router = new Router(); 41 | 42 | const MODEL = process.env.MODEL || 'text-davinci-003'; 43 | const RESPONSE_LIMIT = parseInt(process.env.RESPONSE_LIMIT,10)||512; 44 | const TEMPERATURE = parseFloat(process.env.TEMPERATURE) || 0.25; 45 | 46 | setResponseLimit(RESPONSE_LIMIT); 47 | 48 | const agent = new https.Agent({ keepAlive: true, keepAliveMsecs: 120000, scheduling: 'lifo', family: 0, noDelay: false, zonread: { buffer: Buffer.alloc(RESPONSE_LIMIT * 2.75) } }); 49 | 50 | let completion = ""; 51 | let partial = ""; 52 | let carry = "{"; 53 | let apiServer = ""; 54 | let booting = true; 55 | 56 | const extractText = (chunk) => { 57 | let json; 58 | try { 59 | json = JSON5.parse(`${carry}${chunk}}`); 60 | carry = "{"; 61 | if (parseInt(debug(),10) >= 3) console.log(`${colour.cyan}${chunk}${colour.normal}`); 62 | } 63 | catch (ex) { 64 | carry += chunk; 65 | return; 66 | } 67 | let text; 68 | if (json.data && json.data.choices) { 69 | if (json.data.choices[0].delta) { 70 | text = json.data.choices[0].delta.content; 71 | } 72 | else { 73 | text = json.data.choices[0].text; 74 | } 75 | } 76 | else if (json.data && json.data.stop&& json.data.completion) { 77 | text = json.data.completion; 78 | } 79 | if (text) { 80 | if (!booting) process.stdout.write(text); 81 | completion += text; 82 | } 83 | return text; 84 | } 85 | 86 | const app = new Koa(); 87 | app.use(serve('.')); 88 | router.get('/', '/', (ctx) => { 89 | ctx.body = fiddleSrc; 90 | }); 91 | router.get('/', '/temp.png', (ctx) => { 92 | ctx.body = fs.readFileSync('./temp.png'); 93 | }); 94 | 95 | app 96 | .use(router.routes()) 97 | .use(router.allowedMethods()); 98 | try { 99 | app.listen(parseInt(process.env.PORT,10)||1337); 100 | } 101 | catch (ex) { 102 | tools.disable.execute('savetext'); 103 | tools.disable.execute('savehtml'); 104 | tools.disable.execute('savecode'); 105 | tools.disable.execute('savecss'); 106 | } 107 | 108 | let localHistory = []; 109 | try { 110 | localHistory = yaml.parse(fs.readFileSync('./history.yaml','utf8')); 111 | } 112 | catch (ex) {} 113 | process.env.CHAT_QUERIES = localHistory.join(', '); 114 | 115 | const rl = readline.createInterface({ input, output, history: localHistory, removeHistoryDuplicates: true }); 116 | 117 | const promptTemplate = fs.readFileSync("./prompt.txt", "utf8"); 118 | const mergeTemplate = fs.readFileSync("./merge.txt", "utf8"); 119 | 120 | const consume = async (value, chunkNo) => { 121 | const chunks = `${Buffer.from(value).toString()}`.split('\n'); 122 | for (let chunk of chunks) { 123 | if (booting && chunkNo % 20 === 1) process.stdout.write('.') 124 | chunk = chunk.replaceAll('[DONE]', '["DONE"]'); 125 | extractText(chunk); 126 | } 127 | } 128 | 129 | async function fetchStream(url, options) { 130 | let chunkNo = 0; 131 | let response = { ok: false, status: 418 } 132 | try { 133 | response = await fetch(url, options); 134 | } 135 | catch (ex) { 136 | console.warn(`${colour.red}${ex.message}${colour.normal}`); 137 | } 138 | if (response.status !== 200) { 139 | process.stdout.write(`${colour.red}`); 140 | let text = await response.text(); 141 | try { 142 | let json = JSON5.parse(partial+text); 143 | if (json.error && json.error.message) { 144 | completion += json.error.message; 145 | return text; 146 | } 147 | else { 148 | partial = ""; 149 | } 150 | } 151 | catch (ex) { 152 | partial = text; 153 | } 154 | return text; 155 | } 156 | const reader = response.body.getReader(); 157 | const stream = new ReadableStream({ 158 | start(controller) { 159 | function push() { 160 | reader.read().then(({ done, value }) => { 161 | if (done) { 162 | controller.close(); 163 | return; 164 | } 165 | if (value) consume(value, ++chunkNo); 166 | controller.enqueue(value); 167 | push(); 168 | }); 169 | } 170 | push(); 171 | }, 172 | error (err) { 173 | console.log(`${colour.red}(${err.message})${colour.normal}`); 174 | }, 175 | end () { 176 | if (debug()) console.log(`${colour.cyan}(End of stream)${colour.normal}`); 177 | } 178 | }); 179 | const newResponse = new Response(stream); 180 | const text = await newResponse.text(); 181 | return text; 182 | } 183 | 184 | const getCompletion = async (prompt) => { 185 | process.stdout.write(colour.grey); 186 | completion = ""; 187 | if (process.env.PROVIDER === "anthropic") { 188 | await anthropicCompletion(prompt, fetchStream, agent); 189 | } 190 | else { 191 | await openaiCompletion(prompt, fetchStream, agent); 192 | } 193 | if (!completion.endsWith('\n\n')) { 194 | completion += '\n'; 195 | } 196 | return clean(completion); 197 | } 198 | 199 | const answerQuestion = async (question) => { 200 | // construct the prompt, with our question and the tools that the chain can use 201 | let prompt = promptTemplate.replace("${question}", question).replace( 202 | "${tools}", 203 | Object.keys(tools) 204 | .map((toolname) => `${toolname}: ${tools[toolname].description}`) 205 | .join("\n")) 206 | .replace("${toolList}", Object.keys(tools).join(", ")) 207 | .replace("${user}", process.env.USER) 208 | .replace('${language}',process.env.LANG); 209 | process.env.PROMPT = prompt; 210 | process.env.CHAT_PROMPT = prompt; 211 | 212 | if (process.env.PROMPT_OVERRIDE) { 213 | prompt = process.env.PROMPT_OVERRIDE.replaceAll("${question}", question); 214 | } 215 | 216 | // allow the LLM to iterate until it finds a final answer 217 | while (true) { 218 | const response = await getCompletion(prompt); 219 | 220 | // add this to the prompt 221 | prompt += response; 222 | 223 | // display any embedded image URLs 224 | scanEmbeddedImages(response); 225 | 226 | if (response.indexOf('Action:') >= 0) { 227 | const action = response.split('Action:').pop().split('\n')[0].toLowerCase().trim(); 228 | if (action && tools[action]) { 229 | // execute the action specified by the LLM 230 | let actionInput = response.split('Action Input:').pop().trim(); 231 | if (actionInput.indexOf("```") >= 0) { 232 | actionInput = actionInput.replace(/```.+/gi, "```"); 233 | actionInput = actionInput.split("```")[1]; 234 | } 235 | if (actionInput.indexOf(')()') >= 0) { 236 | actionInput = actionInput.split(')()')[0]+')()'.trim(); 237 | } 238 | if (actionInput.indexOf('```') >= 0) { 239 | actionInput = actionInput.split('```\n')[0].trim(); 240 | } 241 | else if (actionInput.startsWith('|')) { 242 | actionInput = actionInput.substring(1).trim(); 243 | } 244 | else { 245 | actionInput = actionInput.split('\n\n')[0].trim(); 246 | } 247 | if (actionInput && !actionInput.startsWith('[')) { 248 | setPrompt(prompt); 249 | if (process.env.SYNTAX) { 250 | actionInput = highlight(actionInput, { language: 'javascript', theme: shTheme, ignoreIllegals: true }); 251 | } 252 | if (!booting) console.log(`${colour.cyan}\nCalling '${action}' with "${actionInput}"${colour.normal}`); 253 | const result = await tools[action].execute(clean(actionInput)); 254 | prompt += `Observation: ${result||'None'}\n`; 255 | } 256 | } 257 | } else { 258 | if (response.indexOf('Answer:') >= 0) { 259 | let answer = response.split('Answer:').pop(); 260 | if (answer) return answer; 261 | } 262 | let answer = response.split('Observation:').pop().trim(); 263 | return answer||'No answer'; // sometimes we don't get a "Final Answer" 264 | } 265 | } 266 | }; 267 | 268 | // merge the chat history with a new question 269 | const mergeHistory = async (question, history) => { 270 | const prompt = mergeTemplate 271 | .replace("${question}", question) 272 | .replace("${history}", history); 273 | return await getCompletion(prompt); 274 | }; 275 | 276 | process.stdout.write(`${colour.cyan}Initialising built-in tools: `); 277 | let allOk = true; 278 | let first = true; 279 | Object.keys(tools).sort().map((toolname) => { 280 | if (!first) { 281 | process.stdout.write(', '); 282 | } 283 | process.stdout.write(`${colour.magenta}${toolname}`); 284 | const result = (async () => await tools[toolname].init())(); 285 | first = false; 286 | if (!result) allOk = false; 287 | return true; 288 | }); 289 | console.log(colour.normal); 290 | 291 | if (localHistory.length && process.env.SEED_QUERIES) { 292 | booting = true; 293 | const query = `Can you get the CHAT_QUERIES so you can remember the previous questions I have asked? You do not need to list them.`; 294 | process.stdout.write(`${colour.cyan}Please wait, bootstrapping conversation${colour.magenta}`); 295 | const response = await answerQuestion(query); 296 | } 297 | 298 | rl.on('history',(history) => { 299 | fs.writeFileSync('./history.yaml',yaml.stringify(history),'utf8'); 300 | }); 301 | 302 | if (!allOk) { 303 | console.log(`\n${colour.cyan}[2] some tools were disabled because of missing API keys or node.js features.${colour.normal}`); 304 | } 305 | 306 | // main loop - answer the user's questions 307 | while (true) { 308 | booting = false; 309 | debugger; 310 | let question = await rl.question(`${colour.red}How can I help? >${colour.grey} `); 311 | let questionLC = question.trim().toLowerCase(); 312 | questionLC = question.split('please').join('').trim(); 313 | let verb = questionLC.split(' ')[0].toLowerCase().trim(); 314 | if (tools[verb] || (verb.startsWith(':') && tools[verb.replace(':','')])) { 315 | verb = verb.replace(':',''); 316 | console.log(`${colour.magenta}${await tools[verb].execute(clean(questionLC.slice(verb.length+1)))}${colour.normal}`); 317 | question = ''; 318 | } 319 | else if (verb.startsWith(':')) { 320 | if (question.startsWith(':q') || question.startsWith(':wq')) { 321 | console.log(`\nSaving history and exiting with 0.`); 322 | process.exit(0); 323 | } 324 | else if (question.startsWith(':syntax')) { 325 | const value = question.split(' ')[1].trim().toLowerCase(); 326 | process.env.SYNTAX = (value === 'on' || value === 'true' || value === '1' || value === 'yes') ? 1 : 0; 327 | question = ''; 328 | } 329 | else if (question.startsWith(':help')) { 330 | question = "How should a novice user get the best out of this chat experience?"; 331 | } 332 | else if (question === (':set')) { 333 | console.log(yaml.stringify(process.env)); 334 | question = ''; 335 | } 336 | else if (question.startsWith(':set ')) { 337 | question = question.replace('=',' '); 338 | question = question.split(' ').join(' '); 339 | let words = question.split(' '); 340 | let key = words[1] 341 | key = key.toUpperCase(); 342 | words.splice(0, 2); 343 | const value = words.join(' '); 344 | process.env[key] = value; 345 | question = ''; 346 | } 347 | } 348 | let answer = ''; 349 | if (question) answer = await answerQuestion(question); 350 | while (process.env.SYNTAX === '1' && answer.indexOf('```\n') >= 0) { 351 | const sections = answer.split('```'); 352 | const preamble = sections[0]; 353 | const language = sections[1].split('\n')[0].trim(); 354 | const code = sections[1].replace(language + '\n', ''); 355 | const tail = sections[2]; 356 | answer = preamble + highlight(code, { language, theme: shTheme, ignoreIllegals: true }) + tail; 357 | } 358 | if (question || answer) { 359 | console.log(`\n${colour.green}${answer.trimStart()}${colour.normal}`); 360 | addToHistory(`Q:${question}\nA:${answer}\n`); 361 | } 362 | } 363 | 364 | -------------------------------------------------------------------------------- /lib/Groups.js: -------------------------------------------------------------------------------- 1 | class GroupsPicker { 2 | 3 | constructor(){ 4 | let selectChoices = document.createElement("select") 5 | let groupsList = document.querySelectorAll(`.groupsList input[type="checkbox"][name="group[]"]`) 6 | let cont = document.querySelector("#choices-select") 7 | 8 | selectChoices.name = "ignore_this_select" 9 | selectChoices.multiple = true 10 | 11 | cont.appendChild(selectChoices) 12 | 13 | this.groupsChoices = new Choices(selectChoices, { 14 | removeItems: true, 15 | removeItemButton: true, 16 | placeholderValue: I18n.editor.groups.placeholder_value, 17 | searchPlaceholderValue: I18n.editor.groups.search_placeholder_value, 18 | noChoicesText: I18n.editor.groups.no_choices_text, 19 | noResultsText: I18n.editor.groups.no_results_text, 20 | itemSelectText: I18n.editor.groups.item_select_text 21 | }) 22 | 23 | // Create a No groups placeholder as the only choice in the selector 24 | if (groupsList.length <= 0){ 25 | this.groupsChoices.setChoices( 26 | [ 27 | { 28 | value: "", 29 | label: I18n.editor.groups.you_have_no_groups, 30 | disabled: true 31 | } 32 | ], "value", "label", false 33 | ) 34 | } 35 | 36 | // Fetch all groups checkboxes and compose fancy choices from them 37 | Array.from(groupsList).forEach((group, index) => { 38 | let label = group.parentNode.querySelector("span").innerHTML 39 | 40 | this.groupsChoices.setChoices( 41 | [ 42 | { 43 | value: group.value, 44 | label: label, 45 | selected: group.checked, 46 | disabled: group.disabled, 47 | customProperties: { 48 | private: true 49 | } 50 | } 51 | ], "value", "label", false 52 | ) 53 | }) 54 | 55 | selectChoices.addEventListener("addItem", (event) => { 56 | let checkbox = this.getCheckbox(event.detail.value) 57 | checkbox.checked = true 58 | this.togglePlaceholder() 59 | }) 60 | 61 | selectChoices.addEventListener("removeItem", (event) => { 62 | let checkbox = this.getCheckbox(event.detail.value) 63 | checkbox.checked = false 64 | this.togglePlaceholder() 65 | }) 66 | 67 | this.togglePlaceholder() 68 | } 69 | 70 | getCheckbox(value){ 71 | return document.querySelector(`.groupsList input[type="checkbox"][name="group[]"][value="${value}"]`) 72 | } 73 | 74 | togglePlaceholder(){ 75 | let choices = document.querySelector(".choices") 76 | let count = document.querySelectorAll(".choices__inner .choices__item") 77 | 78 | if (count.length >= 1){ 79 | choices.classList.add("no-placeholder") 80 | } else { 81 | choices.classList.remove("no-placeholder") 82 | } 83 | } 84 | 85 | clearAll(){ 86 | // uncheck all hidden group checkboxes 87 | let checkboxes = document.querySelectorAll(`.groupsList input[type="checkbox"][name="group[]"]`) 88 | Array.from(checkboxes).forEach((checkbox) => { 89 | checkbox.checked = false 90 | }) 91 | 92 | // clear choices input of all values 93 | this.groupsChoices.highlightAll() 94 | this.groupsChoices.removeHighlightedItems() 95 | } 96 | } 97 | 98 | let choicesScript = document.createElement("script") 99 | choicesScript.src = "https://jsfiddle.net/js/choices.js" 100 | choicesScript.onload = () => { 101 | window.GroupsPickerManager = new GroupsPicker() 102 | } 103 | choicesScript.defer = true 104 | document.body.appendChild(choicesScript) 105 | -------------------------------------------------------------------------------- /lib/anthropic.mjs: -------------------------------------------------------------------------------- 1 | // use the given model to complete a given prompt 2 | export const anthropicCompletion = async (prompt, fetchStream, agent) => { 3 | let res = { ok: false, status: 418 }; 4 | const body = { 5 | prompt, 6 | model: process.env.MODEL, 7 | max_tokens_to_sample: process.env.RESPONSE_LIMIT, 8 | stream: true, 9 | temperature: parseFloat(process.env.TEMPERATURE), 10 | //top_p: TOP_P, 11 | //top_k: TOP_K, 12 | metadata: { 13 | user_id: 'BingChain', 14 | }, 15 | stop_sequences: ["Observation:", "Question:"] 16 | }; 17 | 18 | return await fetchStream(`https://api.anthropic.com/v1/complete`, { 19 | method: "POST", 20 | headers: { 21 | "Content-Type": "application/json", 22 | "X-API-Key": process.env.ANTHROPIC_API_KEY 23 | }, 24 | body: JSON.stringify(body), 25 | redirect: 'follow', 26 | agent 27 | }); 28 | }; 29 | 30 | -------------------------------------------------------------------------------- /lib/colour.mjs: -------------------------------------------------------------------------------- 1 | export const colour = (process.env.NODE_DISABLE_COLORS || !process.stdout.isTTY) ? 2 | { red: '', yellow: '', green: '', blue: '', normal: '', magenta: '', grey: '', cyan: '', 3 | inverse: '' } : 4 | { red: '\x1b[31m', yellow: '\x1b[33;1m', green: '\x1b[32m', blue: '\x1b[34m', magenta: '\x1b[35m', grey: '\x1b[90m', cyan: '\x1b[96m', inverse: '\x1b[7m', normal: '\x1b[27m\x1b[0m' }; 5 | 6 | -------------------------------------------------------------------------------- /lib/openai.mjs: -------------------------------------------------------------------------------- 1 | // use the given model to complete a given prompt 2 | export const openaiCompletion = async (prompt, fetchStream, agent) => { 3 | let res = { ok: false, status: 418 }; 4 | const body = { 5 | model: process.env.MODEL, 6 | max_tokens: parseInt(process.env.RESPONSE_LIMIT, 10), 7 | temperature: parseFloat(process.env.TEMPERATURE), 8 | stream: true, 9 | user: 'BingChain', 10 | //frequency_penalty: 0.25, 11 | n: 1, 12 | stop: ["Observation:", "Question:"] 13 | }; 14 | if (process.env.MODEL.startsWith('text')) { 15 | body.prompt = prompt; 16 | } 17 | else { 18 | body.messages = [ { role: "system", content: "You are a helpful assistant who tries to answer all questions accurately and comprehensively." }, { role: "user", content: prompt } ]; 19 | } 20 | 21 | const url = `https://api.openai.com/v1/${process.env.MODEL.startsWith('text') ? '' : 'chat/'}completions`; 22 | return await fetchStream(url, { 23 | method: "POST", 24 | headers: { 25 | "Content-Type": "application/json", 26 | Authorization: "Bearer " + process.env.OPENAI_API_KEY 27 | }, 28 | body: JSON.stringify(body), 29 | redirect: 'follow', 30 | agent 31 | }); 32 | }; 33 | 34 | -------------------------------------------------------------------------------- /lib/tools.mjs: -------------------------------------------------------------------------------- 1 | // tools that can be used to answer questions 2 | 3 | import env from "dotenv"; 4 | env.config(); 5 | 6 | import fs from "node:fs"; 7 | import http from "node:http"; 8 | import path from "node:path"; 9 | import vm from "node:vm"; 10 | import util from "node:util"; 11 | 12 | import yaml from 'yaml'; 13 | import JSON5 from 'json5'; 14 | import jgexml from 'jgexml/xml2json.js'; 15 | import { Parser } from "expr-eval"; 16 | import metaFetcher from 'meta-fetcher'; 17 | import { svg2png, initialize } from 'svg2png-wasm'; 18 | import jsFiddle from 'jsfiddle'; 19 | import { v4 as uuidv4 } from 'uuid'; 20 | import open from 'open'; 21 | import TurndownService from 'turndown'; 22 | import turndownPluginGfm from 'turndown-plugin-gfm'; 23 | import { isWithinTokenLimit } from 'gpt-tokenizer'; 24 | import { Image, Video, Gif } from 'termview'; 25 | import pdf from "pdf-parse/lib/pdf-parse.js"; 26 | import mammoth from "mammoth"; 27 | import { request, gql } from "graphql-request"; 28 | 29 | import { colour } from "./colour.mjs"; 30 | 31 | const TOKEN_LIMIT = (parseInt(process.env.TOKEN_LIMIT,10)/2.0)||2048; // TODO 32 | 33 | const scriptResult = { prompt: '', chatResponse: '', chatEnvironment: { retrievedText: '' } }; 34 | vm.createContext(scriptResult); 35 | 36 | const html2md = new TurndownService({ headingStyle: 'atx', codeBlockStyle: 'fenced', preformattedCode: true }); 37 | const gfm = turndownPluginGfm.gfm 38 | const tables = turndownPluginGfm.tables 39 | const strikethrough = turndownPluginGfm.strikethrough 40 | 41 | export let history = ''; 42 | export const debug = () => process.env.DEBUG; 43 | let apiServer = ''; 44 | let RESPONSE_LIMIT; 45 | let blocked = new Map(); 46 | 47 | const pluginTemplate = fs.readFileSync("./plugin.txt", "utf8"); 48 | 49 | // Use the gfm, table and strikethrough plugins 50 | html2md.use([gfm, tables, strikethrough]); 51 | html2md.remove(['aside', 'script', 'style', 'frame', 'iframe', 'applet', 'audio', 'canvas', 'datagrid', 'table']); // some of these may be controversial 52 | 53 | const token_cache = new Map(); 54 | export let fiddleSrc = ""; 55 | 56 | export const setResponseLimit = (limit) => { 57 | RESPONSE_LIMIT = limit; 58 | }; 59 | 60 | export const setPrompt = (prompt) => { 61 | scriptResult.prompt = prompt; 62 | return prompt; 63 | }; 64 | 65 | export const setRetrievedText = (received) => { 66 | scriptResult.chatEnvironment.retrievedText = received; 67 | return received; 68 | }; 69 | 70 | export const clean = (text) => { 71 | text = text.replace(/\u001b\[.*?m/g, ""); 72 | return text.replace(/[\u0000-\u0009\u000B-\u001F\u007F-\u009F]/g, ""); 73 | }; 74 | 75 | const truncate = (text) => { 76 | text = text.substring(0,TOKEN_LIMIT*2); 77 | let count = 0; 78 | let scythe = 0.9; 79 | while (!isWithinTokenLimit(history + '\n' + text, TOKEN_LIMIT - RESPONSE_LIMIT, token_cache)) { 80 | count++; 81 | if (count === 1) { 82 | process.stdout.write(`${colour.magenta}(Truncating)${colour.normal}`); 83 | } 84 | text = text.substring(0,Math.round(text.length*scythe)); 85 | if (scythe > 0.1) { 86 | scythe = scythe - 0.1; 87 | } 88 | else { 89 | scythe = scythe * 0.66; 90 | } 91 | } 92 | return text; 93 | }; 94 | 95 | const nop = () => { return true }; 96 | 97 | // use Microsoft Bing to answer the question 98 | const bingSearch = async (question) => { 99 | let hits = 0; 100 | return await fetch( 101 | `https://api.bing.microsoft.com/v7.0/search?q=${escape(question)}`, { redirect: 'follow', headers: {"Ocp-Apim-Subscription-Key": process.env.BING_API_KEY } }) 102 | .then((res) => { 103 | if (res.ok) return res.json() 104 | else { 105 | console.log(`${colour.red}${res.status} - ${http.STATUS_CODES[res.status]}${colour.normal}`); 106 | return {}; 107 | } 108 | }) 109 | .then((res) => { 110 | let results = 'Results:\n'; 111 | // try to pull the answer from various components of the response 112 | if (res && res.images && res.images.value) { 113 | for (let value of res.images.value) { 114 | hits++; 115 | results += `${value.name}:\n${value.description}\nTo retrieve, use this URL ${value.contentUrl} with the image tool.\n`; 116 | } 117 | } 118 | if (res && res.videos && res.videos.value) { 119 | for (let value of res.videos.value) { 120 | hits++; 121 | results += `${value.name}:\n${value.description}\nTo retrieve, use this URL: ${value.contentUrl} with the video tool.\n`; 122 | } 123 | } 124 | if (res && res.webPages && res.webPages.value) { 125 | for (let value of res.webPages.value) { 126 | hits++; 127 | if (value.url.toLowerCase().indexOf('.pdf') > 0) { 128 | results += `${value.name}:\n${value.snippet}\nFor further details, retrievepdf this URL: ${value.url}\n`; 129 | } 130 | if (value.url.toLowerCase().indexOf('.docx') > 0) { 131 | results += `${value.name}:\n${value.snippet}\nFor further details, retrievedoc this URL: ${value.url}\n`; 132 | } 133 | else { 134 | results += `${value.name}:\n${value.snippet}\nFor further details, retrieve this URL: ${value.url}\n`; 135 | } 136 | } 137 | } 138 | if (results.length < 10) { 139 | results += 'None found.'; 140 | } 141 | results += '\nEnd of results.' 142 | if (parseInt(debug(), 10) > 0) console.log(`${colour.yellow}${results}${colour.normal}`) 143 | else console.log(`${colour.cyan}Found ${hits} search results.${colour.normal}`); 144 | return results; 145 | }); 146 | }; 147 | 148 | const retrieveHTML = async (url) => { 149 | return await retrieveURL(url, true); 150 | } 151 | 152 | const retrieveURL = async (url, skipTurndown) => { 153 | if (url.startsWith('"')) { 154 | url = url.replace(/\\"/g, ''); 155 | } 156 | if (url.startsWith("'")) { 157 | url = url.replace(/\\'/g, ''); 158 | } 159 | if (url.toLowerCase().indexOf('.pdf') > 0) { 160 | return await tools.readpdf.execute(url); 161 | } 162 | if (url.toLowerCase().indexOf('.docx') > 0) { 163 | return await tools.readdoc.execute(url); 164 | } 165 | if (url.toLowerCase().indexOf('.svg') > 0) { 166 | return await tools.image.execute(url); 167 | } 168 | let hoist = { ok: false, status: 418 }; 169 | await fetch(url, { redirect: 'follow' }) 170 | .then((res) => { 171 | hoist = res; 172 | return res.text() 173 | }) 174 | .then((txt) => { 175 | let text = txt 176 | if (!skipTurndown) text = html2md.turndown(text); 177 | text = truncate(text); 178 | setRetrievedText(text); 179 | if (debug()) console.log(`${colour.cyan}${text}${colour.normal}`); 180 | return text; 181 | }) 182 | .catch((ex) => { 183 | console.log(`${colour.red}${ex.message} - ${http.STATUS_CODES[hoist.status]}${colour.normal}`); 184 | }); 185 | }; 186 | 187 | const retrieveMetadata = async (url) => { 188 | try { 189 | const res = await metaFetcher(url); 190 | const result = yaml.stringify(res); 191 | if (debug()) console.log(`${colour.yellow}${result}${colour.normal}`) 192 | return setRetrievedText(result); 193 | } 194 | catch (ex) { 195 | console.log(`${colour.red}${ex.message}${colour.normal}`); 196 | } 197 | return 'No metadata found.' 198 | }; 199 | 200 | const retrieveImage = async (url) => { 201 | if (process.env.GUI) { 202 | open(url); 203 | return "The image was displayed successfully in the browser."; 204 | } 205 | try { 206 | if (url.indexOf('.svg') >= 0) { 207 | const res = await fetch(url, { redirect: 'follow', headers: { "Accept": "image/svg+xml" } }); 208 | const svg = await res.text(); 209 | const body = await svg2png(svg); 210 | fs.writeFileSync("./temp.png", body); 211 | process.nextTick(async () => { // idk why this is necessary, but it is 212 | const render = await Image(`http://localhost:${process.env.PORT}/temp.png`); 213 | console.log(`${render}${colour.normal}`); 214 | }); 215 | } 216 | else if (url.indexOf('.gif') >= 0) { 217 | process.nextTick(async () => { // ditto 218 | const render = await Gif(url); 219 | console.log(`${render}${colour.normal}`); 220 | }); 221 | } 222 | else { 223 | process.nextTick(async () => { // ditto 224 | const render = await Image(url); 225 | console.log(`${render}${colour.normal}`); 226 | }); 227 | } 228 | return "The image was displayed successfully in the terminal."; 229 | } 230 | catch (ex) { 231 | return `That URL returned an error: ${ex.message}. Try again if you have more URLs.`; 232 | } 233 | }; 234 | 235 | const retrieveVideo = async (url) => { 236 | let res = { ok: false, status: 418 }; 237 | try { 238 | if (url.indexOf('.gif') >= 0) { 239 | const render = await Gif(url); 240 | console.log(render); 241 | } 242 | else { 243 | const render = await Video(url); 244 | console.log(render); 245 | } 246 | } 247 | catch (ex) { 248 | console.log(`${colour.red}${ex.message}${colour.normal}`); 249 | return `That video could not be displayed. Try again if you have more URLs.`; 250 | } 251 | }; 252 | 253 | const install = async (domain) => { 254 | domain = domain.split('the ').join(''); 255 | domain = domain.split(' plugin').join(''); 256 | domain = domain.replace('http://',''); 257 | domain = domain.replace('https://',''); 258 | const pluginManifest = `https://${domain}/.well-known/ai-plugin.json`; 259 | let res = { ok: false, status: 404 }; 260 | let plugin; 261 | let question = ''; 262 | try { 263 | res = await fetch(pluginManifest, { redirect: 'follow' }); 264 | } 265 | catch (ex) { 266 | console.log(`${colour.red}${ex.message}${colour.normal}`); 267 | } 268 | if (res.ok) { 269 | plugin = await res.json(); 270 | if (debug()) console.log(`${colour.yellow}${yaml.stringify(plugin)}${colour.normal}`) 271 | if (plugin.api.type === 'openapi') { 272 | res = { ok: false, status: 404 }; 273 | try { 274 | res = await fetch(plugin.api.url, { redirect: 'follow' }); 275 | } 276 | catch (ex) {} 277 | if (res.ok) { 278 | const apiDef = await res.text(); 279 | try { 280 | const openApi = yaml.parse(apiDef); 281 | if (openApi && openApi.openapi && openApi.servers) { 282 | apiServer = openApi.servers[0].url; 283 | // TODO substitute all the variable default values 284 | } 285 | const openApiYaml = yaml.stringify(openApi); 286 | question = pluginTemplate + '\n\n' + openApiYaml; 287 | console.log(`${colour.green}Successfully installed the ${domain} plugin and API.${colour.normal}`); 288 | } 289 | catch (ex) { 290 | console.warn(`${colour.red}${ex.message}${colour.normal}`); 291 | } 292 | } 293 | else { 294 | console.log(`${colour.red}Failed to fetch API definition!${colour.normal}`); 295 | } 296 | } 297 | } 298 | else { 299 | console.log(`${colour.red}Failed to fetch plugin manifest!${colour.normal}`); 300 | } 301 | return question; 302 | }; 303 | 304 | const apicall = async (endpoint) => { 305 | const components = endpoint.split(':'); 306 | const method = components[0].toLowerCase(); 307 | components.shift(); 308 | const remaining = components.join(':').trim(); 309 | let path = remaining.split('#')[0]; 310 | if (!path.startsWith('http')) { 311 | path = apiServer+path; 312 | } 313 | const hdrs = remaining.split('#')[1]; 314 | let headers = {}; 315 | if (hdrs) try { 316 | headers = JSON.parse(hdrs); 317 | } 318 | catch (ex) { 319 | console.log(`${colour.red}Could not parse headers map JSON${colour.normal}`); 320 | } 321 | if (!headers.Accept && !headers.accept) { 322 | headers.accept = 'application/json'; 323 | } 324 | headers['User-Agent'] = 'postman-open-technologies/BingChain/1.1.0'; 325 | console.log('Using the',method,'method to call the',path,'endpoint'); 326 | let res = { ok: false, status: 404 }; 327 | try { 328 | res = await fetch(path,{ method, headers }); 329 | } 330 | catch (ex) { 331 | console.log(`${colour.red}${method} ${path} - ${ex.message}${colour.normal}`); 332 | } 333 | if (res.ok) { 334 | const ct = res.headers['content-type']; 335 | console.log(`${colour.green}${res.status} - ${ct||'No Content-Type specified'}.${colour.normal}`); 336 | let contents = await res.text(); 337 | let json; 338 | if (contents.startsWith('<') || (ct && (ct.indexOf('/xml') > 0 || ct.indexOf('+xml') > 0))) { 339 | json = jgexml.xml2json(contents); 340 | } 341 | else { 342 | json = JSON5.parse(contents); 343 | } 344 | if (debug()) console.log(`${colour.yellow}${yaml.stringify(json)}${colour.normal}`); 345 | return truncate(yaml.stringify(json)); 346 | } 347 | return `${res.status} - ${http.STATUS_CODES[res.status]}`; 348 | }; 349 | 350 | const reset = async () => { 351 | console.log(`${colour.cyan}Resetting chat history.${colour.normal}`); 352 | history = ""; 353 | }; 354 | 355 | export const addToHistory = async (text) => { 356 | history += text; 357 | process.env.CHAT_HISTORY = history; 358 | return history; 359 | } 360 | 361 | const script = async (source) => { 362 | let functionOutput = ''; 363 | scriptResult.chatResponse = ''; 364 | let mod; 365 | try { 366 | mod = new vm.SourceTextModule(source, 367 | { identifier: 'temp', context: scriptResult }); 368 | } 369 | catch (ex) { 370 | console.warn(`${colour.red}${ex.message} - ${source}${colour.normal}`); 371 | return `Parsing your script threw an error: ${ex.message}`; 372 | } 373 | 374 | async function linker(specifier, referencingModule) { 375 | return mod; 376 | } 377 | 378 | try { 379 | await mod.link(linker); 380 | console.log(`${colour.green}Evaluating script...${colour.normal}`); 381 | const ok = await mod.evaluate(); 382 | if (ok) console.log(`${colour.green}Result: ${ok}${colour.normal}`); 383 | const ns = mod.namespace; 384 | if (ns.default && typeof ns.default === 'function') { 385 | functionOutput = ns.default(); 386 | } 387 | } 388 | catch (ex) { 389 | console.warn(`${colour.red}${ex.message}${colour.normal}`); 390 | return `Running your script threw an error: ${ex.message}`; 391 | } 392 | if (scriptResult.chatResponse) { 393 | console.log(`${colour.grey}${scriptResult.chatResponse}${colour.normal}`); 394 | return scriptResult.chatResponse; 395 | } 396 | if (functionOutput) { 397 | console.log(`${colour.grey}${functionOutput}${colour.normal}`); 398 | return functionOutput; 399 | } 400 | console.log(`${colour.red}Script produced no results.${colour.normal}`); 401 | return 'No results.'; 402 | }; 403 | 404 | const savecode = async (input) => { 405 | const slug = `./BingChain-${uuidv4()}`; 406 | jsFiddle.saveFiddle({ title: slug, js: input, html: '', css: '' }, (err, body) => { 407 | if (err) console.warn(`${colour.red}${err.message}${colour.normal}`) 408 | else { 409 | fiddleSrc = body.replace('