├── .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 | 
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 |
2 |
3 |
4 |
5 |
11 |
--------------------------------------------------------------------------------
/src/assets/quasar-logo-vertical.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/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 |
2 |
3 | {{ content }}
4 |
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 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 |
12 |
18 |
--------------------------------------------------------------------------------
/src/pages/ChatPage.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | move on!
24 |
25 |
26 |
27 |
28 |
29 |
30 |
32 |
34 |
36 |
37 |
38 |
39 |
40 |
41 |
163 |
164 |
173 |
--------------------------------------------------------------------------------
/src/pages/ErrorNotFound.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 404
6 |
7 |
8 |
9 | Oops. Nothing here...
10 |
11 |
12 |
21 |
22 |
23 |
24 |
25 |
32 |
--------------------------------------------------------------------------------
/src/pages/IndexPage.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 | Define your AI assistant
11 |
13 |
15 | Define major goals of your AI assistant
16 |
17 |
18 |
19 |
21 |
22 |
23 |
24 | Demo
25 | values
26 | Run
27 |
28 |
29 |
30 |
31 |
32 |
33 | Please provide credentials
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
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 | }
--------------------------------------------------------------------------------