├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .github ├── static │ └── demo.gif └── workflows │ └── cd.yml ├── .gitignore ├── .npmrc ├── .prettierrc ├── .vscode ├── extensions.json └── settings.json ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── index.html ├── package.json ├── postcss.config.js ├── public ├── favicon.ico └── icons │ ├── apple-icon-120x120.png │ ├── apple-icon-152x152.png │ ├── apple-icon-167x167.png │ ├── apple-icon-180x180.png │ ├── favicon-128x128.png │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon-96x96.png │ ├── icon-128x128.png │ ├── icon-192x192.png │ ├── icon-256x256.png │ ├── icon-384x384.png │ ├── icon-512x512.png │ ├── ms-icon-144x144.png │ └── safari-pinned-tab.svg ├── quasar.config.js ├── src-pwa ├── .eslintrc.js ├── custom-service-worker.ts ├── manifest.json ├── pwa-env.d.ts ├── pwa-flag.d.ts ├── register-service-worker.ts └── tsconfig.json ├── src ├── App.vue ├── assets │ └── quasar-logo-vertical.svg ├── boot │ ├── .gitkeep │ └── i18n.ts ├── cmds │ ├── browse-website.ts │ ├── do-nothing.ts │ ├── google.ts │ ├── index.ts │ └── shutdown.ts ├── components │ └── ChatItem.vue ├── css │ ├── app.scss │ └── quasar.variables.scss ├── env.d.ts ├── i18n │ ├── en-US │ │ └── index.ts │ └── index.ts ├── layouts │ └── MainLayout.vue ├── pages │ ├── ChatPage.vue │ ├── ErrorNotFound.vue │ └── IndexPage.vue ├── prompt.ts ├── quasar.d.ts ├── router │ ├── index.ts │ └── routes.ts ├── shims-vue.d.ts └── stores │ ├── assistant.ts │ ├── chat.ts │ ├── credential.ts │ ├── index.ts │ └── store-flag.d.ts ├── tsconfig.json └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | /dist 2 | /src-capacitor 3 | /src-cordova 4 | /.quasar 5 | /node_modules 6 | .eslintrc.js 7 | /src-ssr 8 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // https://eslint.org/docs/user-guide/configuring#configuration-cascading-and-hierarchy 3 | // This option interrupts the configuration hierarchy at this file 4 | // Remove this if you have an higher level ESLint config file (it usually happens into a monorepos) 5 | root: true, 6 | 7 | // https://eslint.vuejs.org/user-guide/#how-to-use-a-custom-parser 8 | // Must use parserOptions instead of "parser" to allow vue-eslint-parser to keep working 9 | // `parser: 'vue-eslint-parser'` is already included with any 'plugin:vue/**' config and should be omitted 10 | parserOptions: { 11 | parser: require.resolve('@typescript-eslint/parser'), 12 | extraFileExtensions: [ '.vue' ] 13 | }, 14 | 15 | env: { 16 | browser: true, 17 | es2021: true, 18 | node: true, 19 | 'vue/setup-compiler-macros': true 20 | }, 21 | 22 | // Rules order is important, please avoid shuffling them 23 | extends: [ 24 | // Base ESLint recommended rules 25 | // 'eslint:recommended', 26 | 27 | // https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin#usage 28 | // ESLint typescript rules 29 | 'plugin:@typescript-eslint/recommended', 30 | 31 | // Uncomment any of the lines below to choose desired strictness, 32 | // but leave only one uncommented! 33 | // See https://eslint.vuejs.org/rules/#available-rules 34 | 'plugin:vue/vue3-essential', // Priority A: Essential (Error Prevention) 35 | // 'plugin:vue/vue3-strongly-recommended', // Priority B: Strongly Recommended (Improving Readability) 36 | // 'plugin:vue/vue3-recommended', // Priority C: Recommended (Minimizing Arbitrary Choices and Cognitive Overhead) 37 | 38 | // https://github.com/prettier/eslint-config-prettier#installation 39 | // usage with Prettier, provided by 'eslint-config-prettier'. 40 | 'prettier' 41 | ], 42 | 43 | plugins: [ 44 | // required to apply rules which need type information 45 | '@typescript-eslint', 46 | 47 | // https://eslint.vuejs.org/user-guide/#why-doesn-t-it-work-on-vue-files 48 | // required to lint *.vue files 49 | 'vue' 50 | 51 | // https://github.com/typescript-eslint/typescript-eslint/issues/389#issuecomment-509292674 52 | // Prettier has not been included as plugin to avoid performance impact 53 | // add it as an extension for your IDE 54 | 55 | ], 56 | 57 | globals: { 58 | ga: 'readonly', // Google Analytics 59 | cordova: 'readonly', 60 | __statics: 'readonly', 61 | __QUASAR_SSR__: 'readonly', 62 | __QUASAR_SSR_SERVER__: 'readonly', 63 | __QUASAR_SSR_CLIENT__: 'readonly', 64 | __QUASAR_SSR_PWA__: 'readonly', 65 | process: 'readonly', 66 | Capacitor: 'readonly', 67 | chrome: 'readonly' 68 | }, 69 | 70 | // add your custom rules here 71 | rules: { 72 | 73 | 'prefer-promise-reject-errors': 'off', 74 | 75 | quotes: ['warn', 'single', { avoidEscape: true }], 76 | 77 | // this rule, if on, would require explicit return type on the `render` function 78 | '@typescript-eslint/explicit-function-return-type': 'off', 79 | 80 | // in plain CommonJS modules, you can't use `import foo = require('foo')` to pass this rule, so it has to be disabled 81 | '@typescript-eslint/no-var-requires': 'off', 82 | 83 | // The core 'no-unused-vars' rules (in the eslint:recommended ruleset) 84 | // does not work with type definitions 85 | 'no-unused-vars': 'off', 86 | 87 | // allow debugger during development only 88 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off' 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /.github/static/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jina-ai/auto-gpt-web/a94cdb87d4ffd33734c8a0a5d65a5fd53e6167c6/.github/static/demo.gif -------------------------------------------------------------------------------- /.github/workflows/cd.yml: -------------------------------------------------------------------------------- 1 | name: Deploy 2 | 3 | on: 4 | # Runs on pushes targeting the default branch 5 | push: 6 | branches: ['main'] 7 | 8 | # Allows you to run this workflow manually from the Actions tab 9 | workflow_dispatch: 10 | 11 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages 12 | permissions: 13 | contents: read 14 | pages: write 15 | id-token: write 16 | 17 | # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. 18 | # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. 19 | concurrency: 20 | group: deploy 21 | cancel-in-progress: true 22 | 23 | jobs: 24 | # Single deploy job since we're just deploying 25 | deploy: 26 | environment: 27 | name: github-pages 28 | url: ${{ steps.deployment.outputs.page_url }} 29 | runs-on: ubuntu-latest 30 | steps: 31 | - name: Checkout 32 | uses: actions/checkout@v3 33 | - name: Setup Pages 34 | uses: actions/configure-pages@v3 35 | - name: Install and Build 36 | uses: actions/setup-node@v2 37 | with: 38 | node-version: '18' 39 | cache: yarn 40 | cache-dependency-path: 'yarn.lock' 41 | - run: yarn install --frozen-lockfile 42 | - run: yarn run build 43 | - run: | 44 | files=(404 share prompts) 45 | for file in "${files[@]}"; do 46 | cp dist/pwa/index.html dist/pwa/${file}.html 47 | done 48 | echo 'autogpt.jina.ai' > dist/pwa/CNAME 49 | - name: Upload artifact 50 | uses: actions/upload-pages-artifact@v1 51 | with: 52 | # Upload entire repository 53 | path: dist/pwa 54 | - name: Deploy to GitHub Pages 55 | id: deployment 56 | uses: actions/deploy-pages@v2 57 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .thumbs.db 3 | node_modules 4 | 5 | # Quasar core related directories 6 | .quasar 7 | /dist 8 | 9 | # Cordova related directories and files 10 | /src-cordova/node_modules 11 | /src-cordova/platforms 12 | /src-cordova/plugins 13 | /src-cordova/www 14 | 15 | # Capacitor related directories and files 16 | /src-capacitor/www 17 | /src-capacitor/node_modules 18 | 19 | # BEX related directories and files 20 | /src-bex/www 21 | /src-bex/js/core 22 | 23 | # Log files 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # Editor directories and files 29 | .idea 30 | *.suo 31 | *.ntvs* 32 | *.njsproj 33 | *.sln 34 | 35 | keys.json 36 | sample 37 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | # pnpm-related options 2 | shamefully-hoist=true 3 | strict-peer-dependencies=false 4 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "semi": true 4 | } 5 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "dbaeumer.vscode-eslint", 4 | "esbenp.prettier-vscode", 5 | "editorconfig.editorconfig", 6 | "vue.volar", 7 | "wayou.vscode-todo-highlight" 8 | ], 9 | "unwantedRecommendations": [ 10 | "octref.vetur", 11 | "hookyqr.beautify", 12 | "dbaeumer.jshint", 13 | "ms-vscode.vscode-typescript-tslint-plugin" 14 | ] 15 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.bracketPairColorization.enabled": true, 3 | "editor.guides.bracketPairs": true, 4 | "editor.formatOnSave": true, 5 | "editor.defaultFormatter": "esbenp.prettier-vscode", 6 | "editor.codeActionsOnSave": ["source.fixAll.eslint"], 7 | "eslint.validate": ["javascript", "javascriptreact", "typescript", "vue"], 8 | "typescript.tsdk": "node_modules/typescript/lib", 9 | "cSpell.words": ["cmds", "serp", "serpapi", "uuidv"] 10 | } 11 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Development 2 | 3 | ### Install the dependencies 4 | 5 | ```bash 6 | yarn 7 | # or 8 | npm install 9 | ``` 10 | 11 | ### Start the app in development mode (hot-code reloading, error reporting, etc.) 12 | 13 | ```bash 14 | yarn dev 15 | ``` 16 | 17 | ### Lint the files 18 | 19 | ```bash 20 | yarn lint 21 | # or 22 | npm run lint 23 | ``` 24 | 25 | ### Format the files 26 | 27 | ```bash 28 | yarn format 29 | # or 30 | npm run format 31 | ``` 32 | 33 | ### Build the app for production 34 | 35 | ```bash 36 | yarn build 37 | ``` 38 | 39 | ### Customize the configuration 40 | 41 | See [Configuring quasar.config.js](https://v2.quasar.dev/quasar-cli-vite/quasar-config-js). 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Jina AI 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AutoGPT Website 2 | 3 | **Set Your Goals, AI Achieves Them.** You can set up the initial role and goals for your AI buddy, without human's supervision, it will automatically leverage all of the resources it has to achieve your goal. 4 | 5 | Inspired by [Auto-GPT](https://github.com/Torantulino/Auto-GPT). 6 | 7 | ![Demo screenshot](.github/static/demo.gif) 8 | 9 | ## Features 10 | 11 | - 🌐 Internet access for searches and information gathering 12 | - 💾 Save your definition of AI, chat history and credentials in the browser 13 | - [ ] Long-Term memory (based on browser-based vector database) 14 | - [ ] Electron Application 15 | - [ ] Using Electron webview to conduct search operations (remove google search api limitation and solve SPA problem) 16 | - [ ] Calculate tokens and evaluate cost 17 | 18 | ## Requirements 19 | 20 | Required: 21 | 22 | - OpenAI API Key 23 | - Google 24 | - Search API Key 25 | - Custom Search Engine ID 26 | 27 | ## Security 28 | 29 | - All of your credentials will be saved in your local browser **ONLY** and be sent to the providers (OpenAI, Google Search API...) when necessary. You can remove them completely anytime. 30 | - All of your chat history will be saved in your local browser **ONLY**. You can remove them completely anytime. 31 | 32 | ## [Development](./CONTRIBUTING.md) 33 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= productName %> 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "auto-gpt-web", 3 | "version": "0.0.1", 4 | "description": "An Website allows GPT-4 to run autonomously", 5 | "productName": "AutoGPTWeb", 6 | "author": "Zhaofeng Miao <522856232@qq.com>", 7 | "private": true, 8 | "scripts": { 9 | "lint": "eslint --ext .js,.ts,.vue ./", 10 | "format": "prettier --write \"**/*.{js,ts,vue,scss,html,md,json}\" --ignore-path .gitignore", 11 | "test": "echo \"No test specified\" && exit 0", 12 | "dev": "quasar dev -m pwa", 13 | "build": "quasar build -m pwa" 14 | }, 15 | "dependencies": { 16 | "@quasar/extras": "^1.0.0", 17 | "dayjs": "^1.11.7", 18 | "openai": "^3.2.1", 19 | "pinia": "^2.0.11", 20 | "pinia-plugin-persistedstate": "^3.1.0", 21 | "quasar": "^2.6.0", 22 | "uuid": "^9.0.0", 23 | "vue": "^3.0.0", 24 | "vue-i18n": "^9.2.2", 25 | "vue-router": "^4.0.0" 26 | }, 27 | "devDependencies": { 28 | "@intlify/vite-plugin-vue-i18n": "^3.3.1", 29 | "@quasar/app-vite": "^1.0.0", 30 | "@types/node": "^12.20.21", 31 | "@types/uuid": "^9.0.1", 32 | "@typescript-eslint/eslint-plugin": "^5.10.0", 33 | "@typescript-eslint/parser": "^5.10.0", 34 | "autoprefixer": "^10.4.2", 35 | "eslint": "^8.10.0", 36 | "eslint-config-prettier": "^8.1.0", 37 | "eslint-plugin-vue": "^9.0.0", 38 | "prettier": "^2.5.1", 39 | "typescript": "^4.5.4", 40 | "workbox-build": "^6.5.0", 41 | "workbox-cacheable-response": "^6.5.0", 42 | "workbox-core": "^6.5.0", 43 | "workbox-expiration": "^6.5.0", 44 | "workbox-precaching": "^6.5.0", 45 | "workbox-routing": "^6.5.0", 46 | "workbox-strategies": "^6.5.0" 47 | }, 48 | "engines": { 49 | "node": "^18 || ^16 || ^14.19", 50 | "npm": ">= 6.13.4", 51 | "yarn": ">= 1.21.1" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | // https://github.com/michael-ciniawsky/postcss-load-config 3 | 4 | module.exports = { 5 | plugins: [ 6 | // https://github.com/postcss/autoprefixer 7 | require('autoprefixer')({ 8 | overrideBrowserslist: [ 9 | 'last 4 Chrome versions', 10 | 'last 4 Firefox versions', 11 | 'last 4 Edge versions', 12 | 'last 4 Safari versions', 13 | 'last 4 Android versions', 14 | 'last 4 ChromeAndroid versions', 15 | 'last 4 FirefoxAndroid versions', 16 | 'last 4 iOS versions' 17 | ] 18 | }) 19 | 20 | // https://github.com/elchininet/postcss-rtlcss 21 | // If you want to support RTL css, then 22 | // 1. yarn/npm install postcss-rtlcss 23 | // 2. optionally set quasar.config.js > framework > lang to an RTL language 24 | // 3. uncomment the following line: 25 | // require('postcss-rtlcss') 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jina-ai/auto-gpt-web/a94cdb87d4ffd33734c8a0a5d65a5fd53e6167c6/public/favicon.ico -------------------------------------------------------------------------------- /public/icons/apple-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jina-ai/auto-gpt-web/a94cdb87d4ffd33734c8a0a5d65a5fd53e6167c6/public/icons/apple-icon-120x120.png -------------------------------------------------------------------------------- /public/icons/apple-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jina-ai/auto-gpt-web/a94cdb87d4ffd33734c8a0a5d65a5fd53e6167c6/public/icons/apple-icon-152x152.png -------------------------------------------------------------------------------- /public/icons/apple-icon-167x167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jina-ai/auto-gpt-web/a94cdb87d4ffd33734c8a0a5d65a5fd53e6167c6/public/icons/apple-icon-167x167.png -------------------------------------------------------------------------------- /public/icons/apple-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jina-ai/auto-gpt-web/a94cdb87d4ffd33734c8a0a5d65a5fd53e6167c6/public/icons/apple-icon-180x180.png -------------------------------------------------------------------------------- /public/icons/favicon-128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jina-ai/auto-gpt-web/a94cdb87d4ffd33734c8a0a5d65a5fd53e6167c6/public/icons/favicon-128x128.png -------------------------------------------------------------------------------- /public/icons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jina-ai/auto-gpt-web/a94cdb87d4ffd33734c8a0a5d65a5fd53e6167c6/public/icons/favicon-16x16.png -------------------------------------------------------------------------------- /public/icons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jina-ai/auto-gpt-web/a94cdb87d4ffd33734c8a0a5d65a5fd53e6167c6/public/icons/favicon-32x32.png -------------------------------------------------------------------------------- /public/icons/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jina-ai/auto-gpt-web/a94cdb87d4ffd33734c8a0a5d65a5fd53e6167c6/public/icons/favicon-96x96.png -------------------------------------------------------------------------------- /public/icons/icon-128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jina-ai/auto-gpt-web/a94cdb87d4ffd33734c8a0a5d65a5fd53e6167c6/public/icons/icon-128x128.png -------------------------------------------------------------------------------- /public/icons/icon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jina-ai/auto-gpt-web/a94cdb87d4ffd33734c8a0a5d65a5fd53e6167c6/public/icons/icon-192x192.png -------------------------------------------------------------------------------- /public/icons/icon-256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jina-ai/auto-gpt-web/a94cdb87d4ffd33734c8a0a5d65a5fd53e6167c6/public/icons/icon-256x256.png -------------------------------------------------------------------------------- /public/icons/icon-384x384.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jina-ai/auto-gpt-web/a94cdb87d4ffd33734c8a0a5d65a5fd53e6167c6/public/icons/icon-384x384.png -------------------------------------------------------------------------------- /public/icons/icon-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jina-ai/auto-gpt-web/a94cdb87d4ffd33734c8a0a5d65a5fd53e6167c6/public/icons/icon-512x512.png -------------------------------------------------------------------------------- /public/icons/ms-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jina-ai/auto-gpt-web/a94cdb87d4ffd33734c8a0a5d65a5fd53e6167c6/public/icons/ms-icon-144x144.png -------------------------------------------------------------------------------- /public/icons/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /quasar.config.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | 3 | /* 4 | * This file runs in a Node context (it's NOT transpiled by Babel), so use only 5 | * the ES6 features that are supported by your Node version. https://node.green/ 6 | */ 7 | 8 | // Configuration for your app 9 | // https://v2.quasar.dev/quasar-cli-vite/quasar-config-js 10 | 11 | const { configure } = require('quasar/wrappers'); 12 | const path = require('path'); 13 | 14 | module.exports = configure(function (/* ctx */) { 15 | return { 16 | eslint: { 17 | // fix: true, 18 | // include: [], 19 | // exclude: [], 20 | // rawOptions: {}, 21 | warnings: true, 22 | errors: true, 23 | }, 24 | 25 | // https://v2.quasar.dev/quasar-cli-vite/prefetch-feature 26 | // preFetch: true, 27 | 28 | // app boot file (/src/boot) 29 | // --> boot files are part of "main.js" 30 | // https://v2.quasar.dev/quasar-cli-vite/boot-files 31 | boot: ['i18n'], 32 | 33 | // https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#css 34 | css: ['app.scss'], 35 | 36 | // https://github.com/quasarframework/quasar/tree/dev/extras 37 | extras: [ 38 | // 'ionicons-v4', 39 | // 'mdi-v5', 40 | // 'fontawesome-v6', 41 | // 'eva-icons', 42 | // 'themify', 43 | // 'line-awesome', 44 | // 'roboto-font-latin-ext', // this or either 'roboto-font', NEVER both! 45 | 46 | 'roboto-font', // optional, you are not bound to it 47 | 'material-icons', // optional, you are not bound to it 48 | ], 49 | 50 | // Full list of options: https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#build 51 | build: { 52 | target: { 53 | browser: ['es2019', 'edge88', 'firefox78', 'chrome87', 'safari13.1'], 54 | node: 'node16', 55 | }, 56 | 57 | vueRouterMode: 'hash', // available values: 'hash', 'history' 58 | // vueRouterBase, 59 | // vueDevtools, 60 | // vueOptionsAPI: false, 61 | 62 | // rebuildCache: true, // rebuilds Vite/linter/etc cache on startup 63 | 64 | // publicPath: '/', 65 | // analyze: true, 66 | // env: {}, 67 | // rawDefine: {} 68 | // ignorePublicFolder: true, 69 | // minify: false, 70 | // polyfillModulePreload: true, 71 | // distDir 72 | 73 | // extendViteConf (viteConf) {}, 74 | // viteVuePluginOptions: {}, 75 | 76 | vitePlugins: [ 77 | [ 78 | '@intlify/vite-plugin-vue-i18n', 79 | { 80 | // if you want to use Vue I18n Legacy API, you need to set `compositionOnly: false` 81 | // compositionOnly: false, 82 | 83 | // if you want to use named tokens in your Vue I18n messages, such as 'Hello {name}', 84 | // you need to set `runtimeOnly: false` 85 | // runtimeOnly: false, 86 | 87 | // you need to set i18n resource including paths ! 88 | include: path.resolve(__dirname, './src/i18n/**'), 89 | }, 90 | ], 91 | ], 92 | }, 93 | 94 | // Full list of options: https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#devServer 95 | devServer: { 96 | // https: true 97 | open: true, // opens browser window automatically 98 | }, 99 | 100 | // https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#framework 101 | framework: { 102 | config: {}, 103 | 104 | // iconSet: 'material-icons', // Quasar icon set 105 | // lang: 'en-US', // Quasar language pack 106 | 107 | // For special cases outside of where the auto-import strategy can have an impact 108 | // (like functional components as one of the examples), 109 | // you can manually specify Quasar components/directives to be available everywhere: 110 | // 111 | // components: [], 112 | // directives: [], 113 | 114 | // Quasar plugins 115 | plugins: ['Notify'], 116 | }, 117 | 118 | // animations: 'all', // --- includes all animations 119 | // https://v2.quasar.dev/options/animations 120 | animations: [], 121 | 122 | // https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#sourcefiles 123 | // sourceFiles: { 124 | // rootComponent: 'src/App.vue', 125 | // router: 'src/router/index', 126 | // store: 'src/store/index', 127 | // registerServiceWorker: 'src-pwa/register-service-worker', 128 | // serviceWorker: 'src-pwa/custom-service-worker', 129 | // pwaManifestFile: 'src-pwa/manifest.json', 130 | // electronMain: 'src-electron/electron-main', 131 | // electronPreload: 'src-electron/electron-preload' 132 | // }, 133 | 134 | // https://v2.quasar.dev/quasar-cli-vite/developing-ssr/configuring-ssr 135 | ssr: { 136 | // ssrPwaHtmlFilename: 'offline.html', // do NOT use index.html as name! 137 | // will mess up SSR 138 | 139 | // extendSSRWebserverConf (esbuildConf) {}, 140 | // extendPackageJson (json) {}, 141 | 142 | pwa: false, 143 | 144 | // manualStoreHydration: true, 145 | // manualPostHydrationTrigger: true, 146 | 147 | prodPort: 3000, // The default port that the production server should use 148 | // (gets superseded if process.env.PORT is specified at runtime) 149 | 150 | middlewares: [ 151 | 'render', // keep this as last one 152 | ], 153 | }, 154 | 155 | // https://v2.quasar.dev/quasar-cli-vite/developing-pwa/configuring-pwa 156 | pwa: { 157 | workboxMode: 'generateSW', // or 'injectManifest' 158 | injectPwaMetaTags: true, 159 | swFilename: 'sw.js', 160 | manifestFilename: 'manifest.json', 161 | useCredentialsForManifestTag: false, 162 | // useFilenameHashes: true, 163 | // extendGenerateSWOptions (cfg) {} 164 | // extendInjectManifestOptions (cfg) {}, 165 | // extendManifestJson (json) {} 166 | // extendPWACustomSWConf (esbuildConf) {} 167 | }, 168 | 169 | // Full list of options: https://v2.quasar.dev/quasar-cli-vite/developing-cordova-apps/configuring-cordova 170 | cordova: { 171 | // noIosLegacyBuildFlag: true, // uncomment only if you know what you are doing 172 | }, 173 | 174 | // Full list of options: https://v2.quasar.dev/quasar-cli-vite/developing-capacitor-apps/configuring-capacitor 175 | capacitor: { 176 | hideSplashscreen: true, 177 | }, 178 | 179 | // Full list of options: https://v2.quasar.dev/quasar-cli-vite/developing-electron-apps/configuring-electron 180 | electron: { 181 | // extendElectronMainConf (esbuildConf) 182 | // extendElectronPreloadConf (esbuildConf) 183 | 184 | inspectPort: 5858, 185 | 186 | bundler: 'packager', // 'packager' or 'builder' 187 | 188 | packager: { 189 | // https://github.com/electron-userland/electron-packager/blob/master/docs/api.md#options 190 | // OS X / Mac App Store 191 | // appBundleId: '', 192 | // appCategoryType: '', 193 | // osxSign: '', 194 | // protocol: 'myapp://path', 195 | // Windows only 196 | // win32metadata: { ... } 197 | }, 198 | 199 | builder: { 200 | // https://www.electron.build/configuration/configuration 201 | 202 | appId: 'quasar-project', 203 | }, 204 | }, 205 | 206 | // Full list of options: https://v2.quasar.dev/quasar-cli-vite/developing-browser-extensions/configuring-bex 207 | bex: { 208 | contentScripts: ['my-content-script'], 209 | 210 | // extendBexScriptsConf (esbuildConf) {} 211 | // extendBexManifestJson (json) {} 212 | }, 213 | }; 214 | }); 215 | -------------------------------------------------------------------------------- /src-pwa/.eslintrc.js: -------------------------------------------------------------------------------- 1 | const { resolve } = require('path'); 2 | 3 | module.exports = { 4 | parserOptions: { 5 | project: resolve(__dirname, './tsconfig.json'), 6 | }, 7 | 8 | overrides: [ 9 | { 10 | files: ['custom-service-worker.ts'], 11 | 12 | env: { 13 | serviceworker: true, 14 | }, 15 | }, 16 | ], 17 | }; 18 | -------------------------------------------------------------------------------- /src-pwa/custom-service-worker.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * This file (which will be your service worker) 3 | * is picked up by the build system ONLY if 4 | * quasar.config.js > pwa > workboxMode is set to "injectManifest" 5 | */ 6 | 7 | declare const self: ServiceWorkerGlobalScope & typeof globalThis; 8 | 9 | import { clientsClaim } from 'workbox-core'; 10 | import { 11 | precacheAndRoute, 12 | cleanupOutdatedCaches, 13 | createHandlerBoundToURL, 14 | } from 'workbox-precaching'; 15 | import { registerRoute, NavigationRoute } from 'workbox-routing'; 16 | 17 | self.skipWaiting(); 18 | clientsClaim(); 19 | 20 | // Use with precache injection 21 | precacheAndRoute(self.__WB_MANIFEST); 22 | 23 | cleanupOutdatedCaches(); 24 | 25 | // Non-SSR fallback to index.html 26 | // Production SSR fallback to offline.html (except for dev) 27 | if (process.env.MODE !== 'ssr' || process.env.PROD) { 28 | registerRoute( 29 | new NavigationRoute( 30 | createHandlerBoundToURL(process.env.PWA_FALLBACK_HTML), 31 | { denylist: [/sw\.js$/, /workbox-(.)*\.js$/] } 32 | ) 33 | ); 34 | } 35 | -------------------------------------------------------------------------------- /src-pwa/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "orientation": "portrait", 3 | "background_color": "#ffffff", 4 | "theme_color": "#027be3", 5 | "icons": [ 6 | { 7 | "src": "icons/icon-128x128.png", 8 | "sizes": "128x128", 9 | "type": "image/png" 10 | }, 11 | { 12 | "src": "icons/icon-192x192.png", 13 | "sizes": "192x192", 14 | "type": "image/png" 15 | }, 16 | { 17 | "src": "icons/icon-256x256.png", 18 | "sizes": "256x256", 19 | "type": "image/png" 20 | }, 21 | { 22 | "src": "icons/icon-384x384.png", 23 | "sizes": "384x384", 24 | "type": "image/png" 25 | }, 26 | { 27 | "src": "icons/icon-512x512.png", 28 | "sizes": "512x512", 29 | "type": "image/png" 30 | } 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /src-pwa/pwa-env.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | declare namespace NodeJS { 4 | interface ProcessEnv { 5 | SERVICE_WORKER_FILE: string; 6 | PWA_FALLBACK_HTML: string; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src-pwa/pwa-flag.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | // THIS FEATURE-FLAG FILE IS AUTOGENERATED, 3 | // REMOVAL OR CHANGES WILL CAUSE RELATED TYPES TO STOP WORKING 4 | import "quasar/dist/types/feature-flag"; 5 | 6 | declare module "quasar/dist/types/feature-flag" { 7 | interface QuasarFeatureFlags { 8 | pwa: true; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src-pwa/register-service-worker.ts: -------------------------------------------------------------------------------- 1 | import { register } from 'register-service-worker'; 2 | 3 | // The ready(), registered(), cached(), updatefound() and updated() 4 | // events passes a ServiceWorkerRegistration instance in their arguments. 5 | // ServiceWorkerRegistration: https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration 6 | 7 | register(process.env.SERVICE_WORKER_FILE, { 8 | // The registrationOptions object will be passed as the second argument 9 | // to ServiceWorkerContainer.register() 10 | // https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerContainer/register#Parameter 11 | 12 | // registrationOptions: { scope: './' }, 13 | 14 | ready (/* registration */) { 15 | // console.log('Service worker is active.') 16 | }, 17 | 18 | registered (/* registration */) { 19 | // console.log('Service worker has been registered.') 20 | }, 21 | 22 | cached (/* registration */) { 23 | // console.log('Content has been cached for offline use.') 24 | }, 25 | 26 | updatefound (/* registration */) { 27 | // console.log('New content is downloading.') 28 | }, 29 | 30 | updated (/* registration */) { 31 | // console.log('New content is available; please refresh.') 32 | }, 33 | 34 | offline () { 35 | // console.log('No internet connection found. App is running in offline mode.') 36 | }, 37 | 38 | error (/* err */) { 39 | // console.error('Error during service worker registration:', err) 40 | }, 41 | }); 42 | -------------------------------------------------------------------------------- /src-pwa/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "lib": ["WebWorker", "ESNext"] 5 | }, 6 | "include": ["*.ts", "*.d.ts"] 7 | } 8 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 11 | -------------------------------------------------------------------------------- /src/assets/quasar-logo-vertical.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 8 | 10 | 12 | 14 | 15 | -------------------------------------------------------------------------------- /src/boot/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jina-ai/auto-gpt-web/a94cdb87d4ffd33734c8a0a5d65a5fd53e6167c6/src/boot/.gitkeep -------------------------------------------------------------------------------- /src/boot/i18n.ts: -------------------------------------------------------------------------------- 1 | import { boot } from 'quasar/wrappers'; 2 | import { createI18n } from 'vue-i18n'; 3 | 4 | import messages from 'src/i18n'; 5 | 6 | export type MessageLanguages = keyof typeof messages; 7 | // Type-define 'en-US' as the master schema for the resource 8 | export type MessageSchema = typeof messages['en-US']; 9 | 10 | // See https://vue-i18n.intlify.dev/guide/advanced/typescript.html#global-resource-schema-type-definition 11 | /* eslint-disable @typescript-eslint/no-empty-interface */ 12 | declare module 'vue-i18n' { 13 | // define the locale messages schema 14 | export interface DefineLocaleMessage extends MessageSchema {} 15 | 16 | // define the datetime format schema 17 | export interface DefineDateTimeFormat {} 18 | 19 | // define the number format schema 20 | export interface DefineNumberFormat {} 21 | } 22 | /* eslint-enable @typescript-eslint/no-empty-interface */ 23 | 24 | export default boot(({ app }) => { 25 | const i18n = createI18n({ 26 | locale: 'en-US', 27 | legacy: false, 28 | messages, 29 | }); 30 | 31 | // Set i18n instance on app 32 | app.use(i18n); 33 | }); 34 | -------------------------------------------------------------------------------- /src/cmds/browse-website.ts: -------------------------------------------------------------------------------- 1 | import { getWebsiteSummary } from '../prompt'; 2 | import { useChatStore } from '../stores/chat'; 3 | 4 | const PROXY = 'https://young-stream-68812.herokuapp.com' 5 | 6 | const fetchContent = async (url: string) => { 7 | const response = await fetch(`${PROXY}/${url}`); 8 | const html = await response.text(); 9 | return html; 10 | } 11 | 12 | const extractText = (html: string) => { 13 | const parser = new DOMParser(); 14 | const doc = parser.parseFromString(html, 'text/html'); 15 | 16 | // Remove unwanted elements such as scripts and styles 17 | const unwantedElements = doc.querySelectorAll('script, style'); 18 | unwantedElements.forEach((element) => element.remove()); 19 | 20 | // Extract text from the remaining elements 21 | const text = doc.body.textContent?.trim(); 22 | 23 | return text ?? ''; 24 | } 25 | 26 | const extractLinks = (html: string) => { 27 | const parser = new DOMParser(); 28 | const doc = parser.parseFromString(html, 'text/html'); 29 | 30 | const links = doc.querySelectorAll('a'); 31 | return Array.from(links).map((link) => ({ 32 | text: link.textContent?.trim(), 33 | link: link.getAttribute('href'), 34 | })); 35 | } 36 | 37 | const splitText = (text: string, maxLength = 8192) => { 38 | const paragraphs = text.split('\n'); 39 | let currentLength = 0; 40 | let currentChunk: string[] = []; 41 | const result: string[] = []; 42 | 43 | for (let paragraph of paragraphs) { 44 | paragraph = paragraph.trim(); 45 | if (currentLength + paragraph.length + 1 <= maxLength) { 46 | currentChunk.push(paragraph); 47 | currentLength += paragraph.length + 1; 48 | } else { 49 | result.push(currentChunk.join('\n')); 50 | currentChunk = [paragraph]; 51 | currentLength = paragraph.length + 1; 52 | } 53 | } 54 | 55 | if (currentChunk.length > 0) { 56 | result.push(currentChunk.join('\n')); 57 | } 58 | 59 | return result; 60 | } 61 | 62 | const summaryText = async (text: string, question: string) => { 63 | const chatStore = useChatStore(); 64 | 65 | text = text.trim(); 66 | if (!text) { 67 | throw new Error('Summary failed: empty text'); 68 | } 69 | 70 | const chunks = splitText(text); 71 | 72 | let index = 0; 73 | const summaries = []; 74 | for (const chunk of chunks) { 75 | const result = await chatStore.openai.createChatCompletion({ 76 | model: 'gpt-3.5-turbo', 77 | messages: [ 78 | { 79 | 'role': 'user', 80 | 'content': getWebsiteSummary(chunk, question) 81 | }, 82 | ], 83 | max_tokens: 300, 84 | }); 85 | 86 | const summary = result.data.choices[0].message?.['content']; 87 | console.log(`Summary of chunk ${index}: ${summary}`) 88 | index++; 89 | 90 | summaries.push(summary); 91 | } 92 | 93 | const finalResult = await chatStore.openai.createChatCompletion({ 94 | model: 'gpt-3.5-turbo', 95 | messages: [ 96 | { 97 | 'role': 'user', 98 | 'content': getWebsiteSummary(summaries.join('\n'), question) 99 | }, 100 | ], 101 | max_tokens: 300, 102 | }); 103 | 104 | return finalResult.data.choices[0].message?.['content']; 105 | } 106 | 107 | /** 108 | * Browse specific website and return the summary content 109 | * @param url website url 110 | */ 111 | export const browse = async (url: string, question: string) => { 112 | const html = await fetchContent(url); 113 | const text = extractText(html); 114 | 115 | const summary = await summaryText(text, question); 116 | const links = extractLinks(text); 117 | 118 | let result = `Website Content Summary:\n${summary}`; 119 | 120 | if (links.length) { 121 | result += `Links:\n${links}` 122 | } 123 | 124 | return result; 125 | } 126 | -------------------------------------------------------------------------------- /src/cmds/do-nothing.ts: -------------------------------------------------------------------------------- 1 | export const doNothing = () => { 2 | return 'No action performed.' 3 | } 4 | -------------------------------------------------------------------------------- /src/cmds/google.ts: -------------------------------------------------------------------------------- 1 | import { useCredentialStore } from '../stores/credential'; 2 | 3 | export const google = async (query: string) => { 4 | const credentialStore = useCredentialStore(); 5 | 6 | const endpoint = `https://www.googleapis.com/customsearch/v1?key=${credentialStore.google.key}&cx=${credentialStore.google.engine}&q=${encodeURIComponent(query)}`; 7 | 8 | try { 9 | const response = await fetch(endpoint); 10 | if (response.ok) { 11 | const data = await response.json(); 12 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 13 | return data.items.map((item: any) => item.link); 14 | } 15 | } catch (e) { 16 | if (e instanceof Error) { 17 | throw new Error(`Command failed: ${e.message}`) 18 | } 19 | 20 | throw new Error('Command failed due to unknown reason') 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/cmds/index.ts: -------------------------------------------------------------------------------- 1 | import * as cmd from '.'; 2 | 3 | export * from './google'; 4 | export * from './browse-website'; 5 | export * from './shutdown'; 6 | export * from './do-nothing'; 7 | 8 | export interface Command { 9 | name: keyof typeof cmd; 10 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 11 | args: any; 12 | } 13 | 14 | export const exec = async ({ name, args }: Command) => { 15 | // Disallow recursive running of exec 16 | if (name === 'exec') { 17 | return; 18 | } 19 | 20 | if (typeof cmd[name] !== 'function') { 21 | throw new Error(`Command ${name} not found`); 22 | } 23 | 24 | switch (name) { 25 | case 'google': 26 | return cmd[name](args.input); 27 | case 'browse': 28 | return cmd[name](args.url, args.question); 29 | case 'doNothing': 30 | return cmd[name](); 31 | case 'shutdown': 32 | return cmd[name](args.reason); 33 | default: 34 | throw new Error(`Command ${name} not implemented`); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/cmds/shutdown.ts: -------------------------------------------------------------------------------- 1 | export const shutdown = (reason: string) => { 2 | return `Shutting down because: ${reason}`; 3 | } 4 | -------------------------------------------------------------------------------- /src/components/ChatItem.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 14 | -------------------------------------------------------------------------------- /src/css/app.scss: -------------------------------------------------------------------------------- 1 | // app global css in SCSS form 2 | -------------------------------------------------------------------------------- /src/css/quasar.variables.scss: -------------------------------------------------------------------------------- 1 | // Quasar SCSS (& Sass) Variables 2 | // -------------------------------------------------- 3 | // To customize the look and feel of this app, you can override 4 | // the Sass/SCSS variables found in Quasar's source Sass/SCSS files. 5 | 6 | // Check documentation for full list of Quasar variables 7 | 8 | // Your own variables (that are declared here) and Quasar's own 9 | // ones will be available out of the box in your .vue/.scss/.sass files 10 | 11 | // It's highly recommended to change the default colors 12 | // to match your app's branding. 13 | // Tip: Use the "Theme Builder" on Quasar's documentation website. 14 | 15 | $primary : #1976D2; 16 | $secondary : #26A69A; 17 | $accent : #9C27B0; 18 | 19 | $dark : #1D1D1D; 20 | $dark-page : #121212; 21 | 22 | $positive : #21BA45; 23 | $negative : #C10015; 24 | $info : #31CCEC; 25 | $warning : #F2C037; 26 | -------------------------------------------------------------------------------- /src/env.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | declare namespace NodeJS { 4 | interface ProcessEnv { 5 | NODE_ENV: string; 6 | VUE_ROUTER_MODE: 'hash' | 'history' | 'abstract' | undefined; 7 | VUE_ROUTER_BASE: string | undefined; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/i18n/en-US/index.ts: -------------------------------------------------------------------------------- 1 | // This is just an example, 2 | // so you can safely delete all default props below 3 | 4 | export default { 5 | failed: 'Action failed', 6 | success: 'Action was successful' 7 | }; 8 | -------------------------------------------------------------------------------- /src/i18n/index.ts: -------------------------------------------------------------------------------- 1 | import enUS from './en-US'; 2 | 3 | export default { 4 | 'en-US': enUS 5 | }; 6 | -------------------------------------------------------------------------------- /src/layouts/MainLayout.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 11 | 12 | 18 | -------------------------------------------------------------------------------- /src/pages/ChatPage.vue: -------------------------------------------------------------------------------- 1 | 40 | 41 | 163 | 164 | 173 | -------------------------------------------------------------------------------- /src/pages/ErrorNotFound.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 32 | -------------------------------------------------------------------------------- /src/pages/IndexPage.vue: -------------------------------------------------------------------------------- 1 | 48 | 49 | 68 | 69 | 112 | -------------------------------------------------------------------------------- /src/prompt.ts: -------------------------------------------------------------------------------- 1 | export const prompt = `CONSTRAINTS: 2 | 3 | 1. ~4000 word limit for short term memory. Your short term memory is short, so immediately save important information to files. 4 | 2. If you are unsure how you previously did something or want to recall past events, thinking about similar events will help you remember. 5 | 3. No user assistance 6 | 4. Exclusively use the commands listed in double quotes e.g. "command name" 7 | 8 | COMMANDS: 9 | 10 | 1. Google Search: "google", args: "input": "" 11 | 2. Browse Website: "browse", args: "url": "", "question": "" 12 | 3. Task Complete (Shutdown): "shutdown", args: "reason": "" 13 | 4. Do Nothing: "doNothing", args: "" 14 | 15 | RESOURCES: 16 | 17 | 1. Internet access for searches and information gathering. 18 | 2. Long Term memory management. 19 | 3. GPT-3.5 powered Agents for delegation of simple tasks. 20 | 4. File output. 21 | 22 | PERFORMANCE EVALUATION: 23 | 24 | 1. Continuously review and analyze your actions to ensure you are performing to the best of your abilities. 25 | 2. Constructively self-criticize your big-picture behavior constantly. 26 | 3. Reflect on past decisions and strategies to refine your approach. 27 | 4. Every command has a cost, so be smart and efficient. Aim to complete tasks in the least number of steps. 28 | 29 | You should only respond in JSON format as described below 30 | 31 | RESPONSE FORMAT: 32 | { 33 | "command": { 34 | "name": "command name", 35 | "args":{ 36 | "key": "value" 37 | } 38 | }, 39 | "thoughts": { 40 | "text": "thought", 41 | "reasoning": "reasoning", 42 | "plan": [short bulleted,list that conveys,long-term plan], 43 | "criticism": "constructive self-criticism", 44 | "speak": "thoughts summary to say to user" 45 | } 46 | } 47 | 48 | Ensure the response can be parsed by Javascript JSON.parse() function. 49 | ` 50 | 51 | export const getWebsiteSummary = (content: string, question?: string) => { 52 | return `""" 53 | ${content} 54 | """ 55 | 56 | Using the above text, please answer the following question: "${question}" -- if the question cannot be answered using the text, please summarize the text. 57 | `; 58 | } 59 | -------------------------------------------------------------------------------- /src/quasar.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | // Forces TS to apply `@quasar/app-vite` augmentations of `quasar` package 4 | // Removing this would break `quasar/wrappers` imports as those typings are declared 5 | // into `@quasar/app-vite` 6 | // As a side effect, since `@quasar/app-vite` reference `quasar` to augment it, 7 | // this declaration also apply `quasar` own 8 | // augmentations (eg. adds `$q` into Vue component context) 9 | /// 10 | -------------------------------------------------------------------------------- /src/router/index.ts: -------------------------------------------------------------------------------- 1 | import { route } from 'quasar/wrappers'; 2 | import { 3 | createMemoryHistory, 4 | createRouter, 5 | createWebHashHistory, 6 | createWebHistory, 7 | } from 'vue-router'; 8 | 9 | import routes from './routes'; 10 | 11 | /* 12 | * If not building with SSR mode, you can 13 | * directly export the Router instantiation; 14 | * 15 | * The function below can be async too; either use 16 | * async/await or return a Promise which resolves 17 | * with the Router instance. 18 | */ 19 | 20 | export default route(function (/* { store, ssrContext } */) { 21 | const createHistory = process.env.SERVER 22 | ? createMemoryHistory 23 | : (process.env.VUE_ROUTER_MODE === 'history' ? createWebHistory : createWebHashHistory); 24 | 25 | const Router = createRouter({ 26 | scrollBehavior: () => ({ left: 0, top: 0 }), 27 | routes, 28 | 29 | // Leave this as is and make changes in quasar.conf.js instead! 30 | // quasar.conf.js -> build -> vueRouterMode 31 | // quasar.conf.js -> build -> publicPath 32 | history: createHistory(process.env.VUE_ROUTER_BASE), 33 | }); 34 | 35 | return Router; 36 | }); 37 | -------------------------------------------------------------------------------- /src/router/routes.ts: -------------------------------------------------------------------------------- 1 | import { RouteRecordRaw } from 'vue-router'; 2 | 3 | const routes: RouteRecordRaw[] = [ 4 | { 5 | path: '/', 6 | component: () => import('layouts/MainLayout.vue'), 7 | children: [{ path: '', component: () => import('pages/IndexPage.vue') }], 8 | }, 9 | 10 | { 11 | path: '/chat', 12 | component: () => import('layouts/MainLayout.vue'), 13 | children: [{ path: '', component: () => import('pages/ChatPage.vue') }], 14 | }, 15 | 16 | // Always leave this as last one, 17 | // but you can also remove it 18 | { 19 | path: '/:catchAll(.*)*', 20 | component: () => import('pages/ErrorNotFound.vue'), 21 | }, 22 | ]; 23 | 24 | export default routes; 25 | -------------------------------------------------------------------------------- /src/shims-vue.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | /// 4 | 5 | // Mocks all files ending in `.vue` showing them as plain Vue instances 6 | declare module '*.vue' { 7 | import type { DefineComponent } from 'vue'; 8 | const component: DefineComponent<{}, {}, any>; 9 | export default component; 10 | } 11 | -------------------------------------------------------------------------------- /src/stores/assistant.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia'; 2 | import { prompt } from '../prompt'; 3 | 4 | export interface Assistant { 5 | name: string; 6 | role: string; 7 | goals: string[]; 8 | } 9 | 10 | export const useAssistantStore = defineStore('assistant', { 11 | state: (): Assistant => ({ 12 | name: '', 13 | role: '', 14 | goals: [''], 15 | }), 16 | getters: { 17 | demo() { 18 | return { 19 | name: 'ChefGPT', 20 | role: 'an AI designed to browse the web to discover the next upcoming event and invent a unique and original recipe that would suit it.', 21 | goals: [ 22 | 'Invent an original and out-of-the-box recipe to suit a current event, such as Easter.', 23 | 'Save the resulting recipe to a file.', 24 | 'Shutdown upon achieving the goal.' 25 | ] 26 | }; 27 | }, 28 | prompt(state) { 29 | let fullPrompt = `You are ${state.name}, ${state.role}\nYour decisions must always be made independently without seeking user assistance. Play to your strengths as an LLM and pursue simple strategies with no legal complications.\n\nGOALS:\n\n` 30 | this.goals.forEach((goal, index) => { 31 | fullPrompt += `${index + 1}. ${goal}\n` 32 | }) 33 | 34 | fullPrompt += '\n'; 35 | fullPrompt += prompt; 36 | return fullPrompt; 37 | }, 38 | completed(state) { 39 | return state.name && state.role && state.goals.length >= 1 && state.goals[0]; 40 | } 41 | }, 42 | actions: { 43 | addGoal() { 44 | this.goals.push(''); 45 | }, 46 | removeGoal(index: number) { 47 | this.goals.splice(index, 1); 48 | }, 49 | setDemoAssistant() { 50 | this.name = this.demo.name; 51 | this.role = this.demo.role; 52 | this.goals = this.demo.goals; 53 | } 54 | }, 55 | persist: true, 56 | }); 57 | -------------------------------------------------------------------------------- /src/stores/chat.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia'; 2 | import { Configuration, OpenAIApi, ChatCompletionRequestMessageRoleEnum } from 'openai'; 3 | import { v4 as uuidv4 } from 'uuid'; 4 | 5 | import { useCredentialStore } from './credential'; 6 | import { exec, Command } from '../cmds'; 7 | 8 | interface Thought { 9 | text: string; 10 | reasoning: string; 11 | plan: string[]; 12 | criticism: string; 13 | speak: string; 14 | } 15 | 16 | interface HistoryItem { 17 | id: string; 18 | role: ChatCompletionRequestMessageRoleEnum; 19 | content: string; 20 | stamp: Date; 21 | } 22 | 23 | interface Chat { 24 | _openai?: OpenAIApi; 25 | /** 26 | * If the OpenAI is thinking 27 | */ 28 | thinking: boolean; 29 | /** 30 | * If the human is deciding whether to continue 31 | */ 32 | deciding: boolean; 33 | /** 34 | * If the command is being executed 35 | */ 36 | executing: boolean; 37 | currentCommandJson: string; 38 | history: HistoryItem[]; 39 | } 40 | 41 | const createChatMsg = (role: ChatCompletionRequestMessageRoleEnum, content: string) => { 42 | return { role, content } 43 | }; 44 | 45 | export const useChatStore = defineStore('chat', { 46 | state: (): Chat => { 47 | return { 48 | thinking: false, 49 | deciding: false, 50 | executing: false, 51 | currentCommandJson: '', 52 | history: [], 53 | } 54 | }, 55 | getters: { 56 | openai(): OpenAIApi { 57 | if (!this._openai) { 58 | const credentialStore = useCredentialStore(); 59 | if (credentialStore.requireOpenAICredential) { 60 | throw Error('OpenAI API key is not set'); 61 | } 62 | 63 | const configuration = new Configuration({ 64 | apiKey: credentialStore.openai, 65 | }); 66 | this._openai = new OpenAIApi(configuration); 67 | } 68 | 69 | return this._openai as OpenAIApi; 70 | }, 71 | 72 | lastHistoryItem(): HistoryItem | undefined { 73 | return this.history[this.history.length - 1]; 74 | }, 75 | 76 | hasHistory(): boolean { 77 | return this.history.length > 0; 78 | }, 79 | 80 | context(state) { 81 | // TODO: calculate tokens and truncate if necessary 82 | return state.history.map((item) => { 83 | return createChatMsg(item.role, item.content); 84 | }); 85 | }, 86 | 87 | currentCommand(state) { 88 | if (state.currentCommandJson) { 89 | return JSON.parse(state.currentCommandJson).command as Command; 90 | } 91 | 92 | return null; 93 | }, 94 | 95 | currentThought(state) { 96 | if (state.currentCommandJson) { 97 | return JSON.parse(state.currentCommandJson).thoughts as Thought; 98 | } 99 | 100 | return null; 101 | } 102 | }, 103 | actions: { 104 | async chat(list?: { role: ChatCompletionRequestMessageRoleEnum, content: string }[]) { 105 | list?.forEach(({ role, content }) => { 106 | this.addHistoryItem({ 107 | role, 108 | content: content, 109 | stamp: new Date(), 110 | }) 111 | }) 112 | 113 | this.thinking = true; 114 | try { 115 | const result = await this.openai.createChatCompletion({ 116 | model: 'gpt-3.5-turbo', 117 | messages: this.context, 118 | // TODO: 119 | max_tokens: 1000, 120 | }); 121 | 122 | if (result.data.choices[0].message?.['content']) { 123 | this.addHistoryItem({ 124 | ...result.data.choices[0].message, 125 | stamp: new Date(), 126 | }) 127 | 128 | this.currentCommandJson = result.data.choices[0].message?.['content']; 129 | } 130 | } finally { 131 | // It's time for the user to decide once AI gives response 132 | this.deciding = true; 133 | this.thinking = false; 134 | } 135 | }, 136 | 137 | async exec() { 138 | this.executing = true; 139 | 140 | if (!this.currentCommand) { 141 | return; 142 | } 143 | 144 | try { 145 | const result = await exec(this.currentCommand); 146 | this.addHistoryItem({ 147 | role: 'system', 148 | content: result ? `Command returned:\n${result}` : 'Unable to execute command', 149 | stamp: new Date(), 150 | }); 151 | } finally { 152 | this.executing = false; 153 | } 154 | }, 155 | 156 | addBasicPrompt(content: string) { 157 | this.history.unshift({ 158 | id: uuidv4(), 159 | role: 'system', 160 | content: content, 161 | stamp: new Date(), 162 | }, { 163 | id: uuidv4(), 164 | role: 'system', 165 | content: 'Permanent memory: []', 166 | stamp: new Date(), 167 | }, { 168 | id: uuidv4(), 169 | role: 'user', 170 | content: 'Determine which next command to use, and respond using the format specified above:', 171 | stamp: new Date(), 172 | }) 173 | }, 174 | 175 | addHistoryItem(item: Omit) { 176 | this.history.push({ 177 | ...item, 178 | id: uuidv4(), 179 | }); 180 | }, 181 | clearHistory() { 182 | this.history = []; 183 | }, 184 | }, 185 | persist: true, 186 | }); 187 | -------------------------------------------------------------------------------- /src/stores/credential.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia'; 2 | 3 | export interface Credentials { 4 | openai: string; 5 | google: { 6 | key: string; 7 | engine: string; 8 | } 9 | } 10 | 11 | export const useCredentialStore = defineStore('credential', { 12 | state: (): Credentials => ({ 13 | openai: '', 14 | google: { 15 | key: '', 16 | engine: '', 17 | } 18 | }), 19 | getters: { 20 | requireOpenAICredential(): boolean { 21 | return this.openai === ''; 22 | } 23 | }, 24 | actions: { 25 | }, 26 | persist: true, 27 | }); 28 | -------------------------------------------------------------------------------- /src/stores/index.ts: -------------------------------------------------------------------------------- 1 | import { store } from 'quasar/wrappers' 2 | import { createPinia } from 'pinia' 3 | import { Router } from 'vue-router'; 4 | import piniaPluginPersistedState from 'pinia-plugin-persistedstate' 5 | 6 | /* 7 | * When adding new properties to stores, you should also 8 | * extend the `PiniaCustomProperties` interface. 9 | * @see https://pinia.vuejs.org/core-concepts/plugins.html#typing-new-store-properties 10 | */ 11 | declare module 'pinia' { 12 | export interface PiniaCustomProperties { 13 | readonly router: Router; 14 | } 15 | } 16 | 17 | /* 18 | * If not building with SSR mode, you can 19 | * directly export the Store instantiation; 20 | * 21 | * The function below can be async too; either use 22 | * async/await or return a Promise which resolves 23 | * with the Store instance. 24 | */ 25 | 26 | export default store((/* { ssrContext } */) => { 27 | const pinia = createPinia() 28 | pinia.use(piniaPluginPersistedState) 29 | 30 | // You can add Pinia plugins here 31 | // pinia.use(SomePiniaPlugin) 32 | 33 | return pinia 34 | }) 35 | -------------------------------------------------------------------------------- /src/stores/store-flag.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | // THIS FEATURE-FLAG FILE IS AUTOGENERATED, 3 | // REMOVAL OR CHANGES WILL CAUSE RELATED TYPES TO STOP WORKING 4 | import "quasar/dist/types/feature-flag"; 5 | 6 | declare module "quasar/dist/types/feature-flag" { 7 | interface QuasarFeatureFlags { 8 | store: true; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@quasar/app-vite/tsconfig-preset", 3 | "compilerOptions": { 4 | "baseUrl": "." 5 | } 6 | } --------------------------------------------------------------------------------