aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorA.J. Shulman <Shulman.aj@gmail.com>2024-08-20 15:17:25 -0400
committerA.J. Shulman <Shulman.aj@gmail.com>2024-08-20 15:17:25 -0400
commit4c0c7794c85cfdbcd61a7ee5cb9a29494fd0444b (patch)
treeabf99fc24966e65a0e0db3f8e17ccb6edcff2d4c
parent4b6ce2ffcb82c1a7467ef7ed8b67b97094a8f6b6 (diff)
better styling, now thoughts and actions are hidden, scroll works better
next steps: - [ ] Ensure it doesn’t create more web documents when one already exists - [ ] Citations should not be rendered on the next line but on the same line as the text - [ ] If invalid XML, run get 3.5 to verify and fix XML based one examples - [ ] Making sure if you ask for other information, it doesn’t go to the same website. Providing website history in use rules for the search tool and website scraper tool or in the prompt directly
-rw-r--r--package-lock.json633
-rw-r--r--package.json1
-rw-r--r--src/client/util/CurrentUserUtils.ts2
-rw-r--r--src/client/views/nodes/ChatBox/ChatBox.scss402
-rw-r--r--src/client/views/nodes/ChatBox/ChatBox.tsx101
-rw-r--r--src/client/views/nodes/ChatBox/MessageComponent.scss10
-rw-r--r--src/client/views/nodes/ChatBox/MessageComponent.tsx97
-rw-r--r--src/server/ApiManagers/AssistantManager.ts64
8 files changed, 978 insertions, 332 deletions
diff --git a/package-lock.json b/package-lock.json
index 601addf4e..68c9e9746 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -180,6 +180,7 @@
"prosemirror-transform": "^1.8.0",
"prosemirror-view": "^1.32.5",
"pug": "^3.0.2",
+ "puppeteer": "^23.1.0",
"query-string": "^7.1.3",
"querystring-es3": "^0.2.1",
"raw-loader": "^4.0.2",
@@ -5204,6 +5205,140 @@
"url": "https://opencollective.com/popperjs"
}
},
+ "node_modules/@puppeteer/browsers": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.3.1.tgz",
+ "integrity": "sha512-uK7o3hHkK+naEobMSJ+2ySYyXtQkBxIH8Gn4MK9ciePjNV+Pf+PgY/W7iPzn2MTjl3stcYB5AlcTmPYw7AXDwA==",
+ "dependencies": {
+ "debug": "^4.3.6",
+ "extract-zip": "^2.0.1",
+ "progress": "^2.0.3",
+ "proxy-agent": "^6.4.0",
+ "semver": "^7.6.3",
+ "tar-fs": "^3.0.6",
+ "unbzip2-stream": "^1.4.3",
+ "yargs": "^17.7.2"
+ },
+ "bin": {
+ "browsers": "lib/cjs/main-cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@puppeteer/browsers/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@puppeteer/browsers/node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@puppeteer/browsers/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/@puppeteer/browsers/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ },
+ "node_modules/@puppeteer/browsers/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+ },
+ "node_modules/@puppeteer/browsers/node_modules/semver": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@puppeteer/browsers/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@puppeteer/browsers/node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/@puppeteer/browsers/node_modules/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@puppeteer/browsers/node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/@react-aria/actiongroup": {
"version": "3.7.5",
"resolved": "https://registry.npmjs.org/@react-aria/actiongroup/-/actiongroup-3.7.5.tgz",
@@ -8786,6 +8921,11 @@
"resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz",
"integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="
},
+ "node_modules/@tootallnate/quickjs-emscripten": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz",
+ "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA=="
+ },
"node_modules/@tsconfig/node10": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz",
@@ -11530,6 +11670,15 @@
"resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz",
"integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ=="
},
+ "node_modules/@types/yauzl": {
+ "version": "2.10.3",
+ "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz",
+ "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==",
+ "optional": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
"node_modules/@types/youtube": {
"version": "0.0.50",
"resolved": "https://registry.npmjs.org/@types/youtube/-/youtube-0.0.50.tgz",
@@ -12594,6 +12743,17 @@
"node": ">=0.10.0"
}
},
+ "node_modules/ast-types": {
+ "version": "0.13.4",
+ "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz",
+ "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==",
+ "dependencies": {
+ "tslib": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/ast-types-flow": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz",
@@ -12854,6 +13014,41 @@
"integrity": "sha512-qMKFd2qG/36aA4GwvKq8MxnPgCQAmBWmSyLWsJcbn8v03wvIPQ/hG1Ms8bPzndZxMDoHpxez5VOS+gC9Yi24/Q==",
"optional": true
},
+ "node_modules/bare-fs": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-2.3.1.tgz",
+ "integrity": "sha512-W/Hfxc/6VehXlsgFtbB5B4xFcsCl+pAh30cYhoFyXErf6oGrwjh8SwiPAdHgpmWonKuYpZgGywN0SXt7dgsADA==",
+ "optional": true,
+ "dependencies": {
+ "bare-events": "^2.0.0",
+ "bare-path": "^2.0.0",
+ "bare-stream": "^2.0.0"
+ }
+ },
+ "node_modules/bare-os": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-2.4.0.tgz",
+ "integrity": "sha512-v8DTT08AS/G0F9xrhyLtepoo9EJBJ85FRSMbu1pQUlAf6A8T0tEEQGMVObWeqpjhSPXsE0VGlluFBJu2fdoTNg==",
+ "optional": true
+ },
+ "node_modules/bare-path": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-2.1.3.tgz",
+ "integrity": "sha512-lh/eITfU8hrj9Ru5quUp0Io1kJWIk1bTjzo7JH1P5dWmQ2EL4hFUlfI8FonAhSlgIfhn63p84CDY/x+PisgcXA==",
+ "optional": true,
+ "dependencies": {
+ "bare-os": "^2.1.0"
+ }
+ },
+ "node_modules/bare-stream": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.1.3.tgz",
+ "integrity": "sha512-tiDAH9H/kP+tvNO5sczyn9ZAA7utrSMobyDchsnyyXBuUe2FSQWbxhtuHB8jwpHYYevVo2UJpcmvvjrbHboUUQ==",
+ "optional": true,
+ "dependencies": {
+ "streamx": "^2.18.0"
+ }
+ },
"node_modules/Base64": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/Base64/-/Base64-0.2.1.tgz",
@@ -12894,6 +13089,14 @@
"node": ">=6.0.0"
}
},
+ "node_modules/basic-ftp": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz",
+ "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==",
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
"node_modules/batch": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
@@ -16765,6 +16968,19 @@
"node": ">=6.0"
}
},
+ "node_modules/chromium-bidi": {
+ "version": "0.6.4",
+ "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.6.4.tgz",
+ "integrity": "sha512-8zoq6ogmhQQkAKZVKO2ObFTl4uOkqoX1PlKQX3hZQ5E9cbUotcAb7h4pTNVAGGv8Z36PF3CtdOriEp/Rz82JqQ==",
+ "dependencies": {
+ "mitt": "3.0.1",
+ "urlpattern-polyfill": "10.0.0",
+ "zod": "3.23.8"
+ },
+ "peerDependencies": {
+ "devtools-protocol": "*"
+ }
+ },
"node_modules/ci-info": {
"version": "3.9.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
@@ -18345,9 +18561,9 @@
"integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg=="
},
"node_modules/debug": {
- "version": "4.3.5",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz",
- "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==",
+ "version": "4.3.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz",
+ "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==",
"dependencies": {
"ms": "2.1.2"
},
@@ -18582,6 +18798,19 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/degenerator": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz",
+ "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==",
+ "dependencies": {
+ "ast-types": "^0.13.4",
+ "escodegen": "^2.1.0",
+ "esprima": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
"node_modules/delaunator": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz",
@@ -18738,6 +18967,11 @@
"url": "https://github.com/sponsors/wooorm"
}
},
+ "node_modules/devtools-protocol": {
+ "version": "0.0.1312386",
+ "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1312386.tgz",
+ "integrity": "sha512-DPnhUXvmvKT2dFA/j7B+riVLUt9Q6RKJlcppojL5CoRywJJKLDYnRlw0gTFKfgDPHP5E04UoB71SxoJlVZy8FA=="
+ },
"node_modules/dezalgo": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz",
@@ -19011,6 +19245,14 @@
"node": ">=0.10.0"
}
},
+ "node_modules/end-of-stream": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+ "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+ "dependencies": {
+ "once": "^1.4.0"
+ }
+ },
"node_modules/engine.io": {
"version": "6.5.5",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.5.tgz",
@@ -19114,6 +19356,14 @@
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
+ "node_modules/env-paths": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
+ "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/envinfo": {
"version": "7.13.0",
"resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz",
@@ -19343,6 +19593,35 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/escodegen": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz",
+ "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==",
+ "dependencies": {
+ "esprima": "^4.0.1",
+ "estraverse": "^5.2.0",
+ "esutils": "^2.0.2"
+ },
+ "bin": {
+ "escodegen": "bin/escodegen.js",
+ "esgenerate": "bin/esgenerate.js"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "optionalDependencies": {
+ "source-map": "~0.6.1"
+ }
+ },
+ "node_modules/escodegen/node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "optional": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/eslint": {
"version": "8.57.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz",
@@ -21286,6 +21565,39 @@
"resolved": "https://registry.npmjs.org/extract-colors/-/extract-colors-4.0.6.tgz",
"integrity": "sha512-U+pYyQKXCSHOmtZPIEJBGLJjLDiqS+oOub2ILA3a7UGt9+IvZvwAN3hOPFjUgT+gX/apSBwP5vBgnKMlV0fy8Q=="
},
+ "node_modules/extract-zip": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
+ "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
+ "dependencies": {
+ "debug": "^4.1.1",
+ "get-stream": "^5.1.0",
+ "yauzl": "^2.10.0"
+ },
+ "bin": {
+ "extract-zip": "cli.js"
+ },
+ "engines": {
+ "node": ">= 10.17.0"
+ },
+ "optionalDependencies": {
+ "@types/yauzl": "^2.9.1"
+ }
+ },
+ "node_modules/extract-zip/node_modules/get-stream": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
+ "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
+ "dependencies": {
+ "pump": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/extsprintf": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
@@ -21410,6 +21722,14 @@
"node": ">=0.8.0"
}
},
+ "node_modules/fd-slicer": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
+ "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
+ "dependencies": {
+ "pend": "~1.2.0"
+ }
+ },
"node_modules/fetch-blob": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-2.1.2.tgz",
@@ -22480,6 +22800,41 @@
"url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
}
},
+ "node_modules/get-uri": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.3.tgz",
+ "integrity": "sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw==",
+ "dependencies": {
+ "basic-ftp": "^5.0.2",
+ "data-uri-to-buffer": "^6.0.2",
+ "debug": "^4.3.4",
+ "fs-extra": "^11.2.0"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/get-uri/node_modules/data-uri-to-buffer": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz",
+ "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==",
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/get-uri/node_modules/fs-extra": {
+ "version": "11.2.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz",
+ "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==",
+ "dependencies": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=14.14"
+ }
+ },
"node_modules/get-value": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
@@ -24224,6 +24579,28 @@
"loose-envify": "^1.0.0"
}
},
+ "node_modules/ip-address": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz",
+ "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==",
+ "dependencies": {
+ "jsbn": "1.1.0",
+ "sprintf-js": "^1.1.3"
+ },
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/ip-address/node_modules/jsbn": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
+ "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A=="
+ },
+ "node_modules/ip-address/node_modules/sprintf-js": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
+ "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA=="
+ },
"node_modules/ipaddr.js": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
@@ -32566,6 +32943,11 @@
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
},
+ "node_modules/mitt": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
+ "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw=="
+ },
"node_modules/mj-context-menu": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/mj-context-menu/-/mj-context-menu-0.6.1.tgz",
@@ -33083,6 +33465,14 @@
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="
},
+ "node_modules/netmask": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz",
+ "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==",
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
"node_modules/nextafter": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/nextafter/-/nextafter-1.0.0.tgz",
@@ -36182,6 +36572,36 @@
"node": ">=6"
}
},
+ "node_modules/pac-proxy-agent": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.2.tgz",
+ "integrity": "sha512-BFi3vZnO9X5Qt6NRz7ZOaPja3ic0PhlsmCRYLOpN11+mWBCR6XJDqW5RF3j8jm4WGGQZtBA+bTfxYzeKW73eHg==",
+ "dependencies": {
+ "@tootallnate/quickjs-emscripten": "^0.23.0",
+ "agent-base": "^7.0.2",
+ "debug": "^4.3.4",
+ "get-uri": "^6.0.1",
+ "http-proxy-agent": "^7.0.0",
+ "https-proxy-agent": "^7.0.5",
+ "pac-resolver": "^7.0.1",
+ "socks-proxy-agent": "^8.0.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/pac-resolver": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz",
+ "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==",
+ "dependencies": {
+ "degenerator": "^5.0.0",
+ "netmask": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
"node_modules/package-json-from-dist": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz",
@@ -36621,6 +37041,11 @@
"url": "https://github.com/sponsors/Borewit"
}
},
+ "node_modules/pend": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
+ "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg=="
+ },
"node_modules/performance-now": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
@@ -37021,7 +37446,6 @@
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
- "dev": true,
"engines": {
"node": ">=0.4.0"
}
@@ -37175,6 +37599,32 @@
"node": ">= 0.10"
}
},
+ "node_modules/proxy-agent": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz",
+ "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==",
+ "dependencies": {
+ "agent-base": "^7.0.2",
+ "debug": "^4.3.4",
+ "http-proxy-agent": "^7.0.1",
+ "https-proxy-agent": "^7.0.3",
+ "lru-cache": "^7.14.1",
+ "pac-proxy-agent": "^7.0.1",
+ "proxy-from-env": "^1.1.0",
+ "socks-proxy-agent": "^8.0.2"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/proxy-agent/node_modules/lru-cache": {
+ "version": "7.18.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
+ "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
@@ -37302,6 +37752,15 @@
"resolved": "https://registry.npmjs.org/pug-walk/-/pug-walk-2.0.0.tgz",
"integrity": "sha512-yYELe9Q5q9IQhuvqsZNwA5hfPkMJ8u92bQLIMcsMxf/VADjNtEYptU+inlufAFYcWdHlwNfZOEnOOQrZrcyJCQ=="
},
+ "node_modules/pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "dependencies": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
"node_modules/punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
@@ -37318,6 +37777,83 @@
"node": ">=6"
}
},
+ "node_modules/puppeteer": {
+ "version": "23.1.0",
+ "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-23.1.0.tgz",
+ "integrity": "sha512-m+CyicDlGN1AVUeOsCa6/+KQydJzxfsPowL7fQy+VGNeaWafB0m8G5aGfXdfZztKMxzCsdz7KNNzbJPeG9wwFw==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "@puppeteer/browsers": "2.3.1",
+ "chromium-bidi": "0.6.4",
+ "cosmiconfig": "^9.0.0",
+ "devtools-protocol": "0.0.1312386",
+ "puppeteer-core": "23.1.0",
+ "typed-query-selector": "^2.12.0"
+ },
+ "bin": {
+ "puppeteer": "lib/cjs/puppeteer/node/cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/puppeteer-core": {
+ "version": "23.1.0",
+ "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-23.1.0.tgz",
+ "integrity": "sha512-SvAsu+xnLN2FMXE/59bp3s3WXp8ewqUGzVV4AQtml/2xmsciZnU/bXcCW+eETHPWQ6Agg2vTI7QzWXPpEARK2g==",
+ "dependencies": {
+ "@puppeteer/browsers": "2.3.1",
+ "chromium-bidi": "0.6.4",
+ "debug": "^4.3.6",
+ "devtools-protocol": "0.0.1312386",
+ "typed-query-selector": "^2.12.0",
+ "ws": "^8.18.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/puppeteer/node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
+ },
+ "node_modules/puppeteer/node_modules/cosmiconfig": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz",
+ "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==",
+ "dependencies": {
+ "env-paths": "^2.2.1",
+ "import-fresh": "^3.3.0",
+ "js-yaml": "^4.1.0",
+ "parse-json": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/d-fischer"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.9.5"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/puppeteer/node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
"node_modules/q": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz",
@@ -40274,6 +40810,15 @@
"node": ">=4"
}
},
+ "node_modules/smart-buffer": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
+ "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
+ "engines": {
+ "node": ">= 6.0.0",
+ "npm": ">= 3.0.0"
+ }
+ },
"node_modules/socket.io": {
"version": "4.7.5",
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz",
@@ -40366,6 +40911,32 @@
"uuid": "dist/bin/uuid"
}
},
+ "node_modules/socks": {
+ "version": "2.8.3",
+ "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz",
+ "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==",
+ "dependencies": {
+ "ip-address": "^9.0.5",
+ "smart-buffer": "^4.2.0"
+ },
+ "engines": {
+ "node": ">= 10.0.0",
+ "npm": ">= 3.0.0"
+ }
+ },
+ "node_modules/socks-proxy-agent": {
+ "version": "8.0.4",
+ "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz",
+ "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==",
+ "dependencies": {
+ "agent-base": "^7.1.1",
+ "debug": "^4.3.4",
+ "socks": "^2.8.3"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
"node_modules/sort-asc": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/sort-asc/-/sort-asc-0.2.0.tgz",
@@ -41241,6 +41812,19 @@
"node": ">=10"
}
},
+ "node_modules/tar-fs": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.6.tgz",
+ "integrity": "sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==",
+ "dependencies": {
+ "pump": "^3.0.0",
+ "tar-stream": "^3.1.5"
+ },
+ "optionalDependencies": {
+ "bare-fs": "^2.1.1",
+ "bare-path": "^2.1.0"
+ }
+ },
"node_modules/tar-stream": {
"version": "3.1.7",
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz",
@@ -41403,8 +41987,7 @@
"node_modules/through": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
- "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
- "dev": true
+ "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="
},
"node_modules/thunky": {
"version": "1.1.0",
@@ -42350,6 +42933,11 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/typed-query-selector": {
+ "version": "2.12.0",
+ "resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.0.tgz",
+ "integrity": "sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg=="
+ },
"node_modules/typescript": {
"version": "5.5.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz",
@@ -42458,6 +43046,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/unbzip2-stream": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz",
+ "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==",
+ "dependencies": {
+ "buffer": "^5.2.1",
+ "through": "^2.3.8"
+ }
+ },
"node_modules/undefsafe": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz",
@@ -42860,6 +43457,11 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/urlpattern-polyfill": {
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz",
+ "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg=="
+ },
"node_modules/use-composed-ref": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.3.0.tgz",
@@ -43968,7 +44570,6 @@
"version": "8.18.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
"integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
- "dev": true,
"engines": {
"node": ">=10.0.0"
},
@@ -44161,6 +44762,23 @@
"node": ">=8"
}
},
+ "node_modules/yauzl": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
+ "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
+ "dependencies": {
+ "buffer-crc32": "~0.2.3",
+ "fd-slicer": "~1.1.0"
+ }
+ },
+ "node_modules/yauzl/node_modules/buffer-crc32": {
+ "version": "0.2.13",
+ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
+ "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/yn": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
@@ -44198,7 +44816,6 @@
"version": "3.23.8",
"resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz",
"integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==",
- "peer": true,
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
diff --git a/package.json b/package.json
index 544917e78..57a8ffc05 100644
--- a/package.json
+++ b/package.json
@@ -265,6 +265,7 @@
"prosemirror-transform": "^1.8.0",
"prosemirror-view": "^1.32.5",
"pug": "^3.0.2",
+ "puppeteer": "^23.1.0",
"query-string": "^7.1.3",
"querystring-es3": "^0.2.1",
"raw-loader": "^4.0.2",
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index e095bc659..280830442 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -371,7 +371,7 @@ pie title Minerals in my tap water
{key: "Button", creator: Docs.Create.ButtonDocument, opts: { _width: 150, _height: 50, _xPadding: 10, _yPadding: 10, title_custom: true, waitForDoubleClickToClick: 'never'}, scripts: {onClick: FollowLinkScript()?.script.originalScript ?? ""}},
{key: "Script", creator: opts => Docs.Create.ScriptingDocument(null, opts), opts: { _width: 200, _height: 250, }},
{key: "DataViz", creator: opts => Docs.Create.DataVizDocument("/users/rz/Downloads/addresses.csv", opts), opts: { _width: 300, _height: 300 }},
- {key: "Chat", creator: Docs.Create.ChatDocument, opts: { _width: 300, _height: 300, }},
+ {key: "Chat", creator: Docs.Create.ChatDocument, opts: { _width: 500, _height: 500, }},
{key: "Header", creator: headerTemplate, opts: { _width: 300, _height: 120, _header_pointerEvents: "all", _header_height: 50, _header_fontSize: 9,_layout_autoHeightMargins: 50, _layout_autoHeight: true, treeView_HideUnrendered: true}},
{key: "ViewSlide", creator: slideView, opts: { _width: 400, _height: 300, _xMargin: 3, _yMargin: 3,}},
{key: "Trail", creator: Docs.Create.PresDocument, opts: { _width: 400, _height: 30, _type_collection: CollectionViewType.Stacking, dropAction: dropActionType.embed, treeView_HideTitle: true, _layout_fitWidth:true, layout_boxShadow: "0 0" }},
diff --git a/src/client/views/nodes/ChatBox/ChatBox.scss b/src/client/views/nodes/ChatBox/ChatBox.scss
index 91bb3aba7..76fa05ce8 100644
--- a/src/client/views/nodes/ChatBox/ChatBox.scss
+++ b/src/client/views/nodes/ChatBox/ChatBox.scss
@@ -1,246 +1,246 @@
-$background-color: #f8f9fa;
+@import url('https://fonts.googleapis.com/css2?family=Atkinson+Hyperlegible:ital,wght@0,400;0,700;1,400;1,700&display=swap');
+
+$primary-color: #4a90e2;
+$secondary-color: #f5f8fa;
$text-color: #333;
-$input-background: #fff;
-$button-color: #007bff;
-$button-hover-color: darken($button-color, 10%);
-$shadow-color: rgba(0, 0, 0, 0.075);
-$border-radius: 8px;
-$citation-color: #ff6347;
-$citation-hover-color: darken($citation-color, 10%);
-$follow-up-bg-color: #e9ecef;
-$follow-up-hover-bg-color: #dee2e6;
-
-.chatBox {
+$light-text-color: #777;
+$border-color: #e1e8ed;
+$shadow-color: rgba(0, 0, 0, 0.1);
+$transition: all 0.3s ease;
+
+.chat-box {
display: flex;
flex-direction: column;
- width: 100%;
height: 100%;
- background-color: $background-color;
- font-family: 'Helvetica Neue', Arial, sans-serif;
+ background-color: #fff;
+ font-family:
+ 'Atkinson Hyperlegible',
+ -apple-system,
+ BlinkMacSystemFont,
+ 'Segoe UI',
+ Roboto,
+ Helvetica,
+ Arial,
+ sans-serif;
+ border-radius: 12px;
+ overflow: hidden;
+ box-shadow: 0 4px 12px $shadow-color;
+
+ .chat-header {
+ background-color: $primary-color;
+ color: white;
+ padding: 15px;
+ text-align: center;
+ box-shadow: 0 2px 4px $shadow-color;
+ height: fit-content;
+ h2 {
+ margin: 0;
+ font-size: 1.3em;
+ font-weight: 500;
+ }
+ }
- .scroll-box {
+ .chat-messages {
flex-grow: 1;
- overflow-y: scroll;
- overflow-x: hidden;
- height: 100%;
- padding: 10px;
+ overflow-y: auto;
+ padding: 20px;
display: flex;
- flex-direction: column-reverse;
- padding-bottom: 0;
+ flex-direction: column;
&::-webkit-scrollbar {
- width: 8px;
+ width: 6px;
}
+
&::-webkit-scrollbar-thumb {
- background-color: darken($background-color, 10%);
- border-radius: $border-radius;
+ background-color: $border-color;
+ border-radius: 3px;
}
+ }
- .chat-content {
- display: flex;
- flex-direction: column;
+ .chat-input {
+ display: flex;
+ padding: 20px;
+ border-top: 1px solid $border-color;
+ background-color: #fff;
+
+ input {
+ flex-grow: 1;
+ padding: 12px 15px;
+ border: 1px solid $border-color;
+ border-radius: 24px;
+ font-size: 15px;
+ transition: $transition;
+
+ &:focus {
+ outline: none;
+ border-color: $primary-color;
+ box-shadow: 0 0 0 2px rgba($primary-color, 0.2);
+ }
}
- .messages {
+ .submit-button {
+ background-color: $primary-color;
+ color: white;
+ border: none;
+ border-radius: 50%;
+ width: 48px;
+ height: 48px;
+ margin-left: 10px;
+ cursor: pointer;
+ transition: $transition;
display: flex;
- flex-direction: column;
-
- .message {
- padding: 10px 15px;
- margin-bottom: 10px;
- border-radius: $border-radius;
- background-color: lighten($background-color, 5%);
- box-shadow: 0 2px 5px $shadow-color;
- align-items: flex-start;
- max-width: 90%;
- width: fit-content;
- word-break: break-word;
- position: relative;
-
- .citation-button {
- background-color: $citation-color;
- color: #fff;
- border: none;
- border-radius: 50%;
- cursor: pointer;
- width: 20px;
- height: 20px;
- display: inline-flex;
- align-items: center;
- justify-content: center;
- font-size: 12px;
- font-weight: bold;
- margin: 0 2px;
- padding: 0;
- transition: background-color 0.3s;
-
- &:hover {
- background-color: $citation-hover-color;
- }
- }
-
- &.user {
- align-self: flex-end;
- background-color: $button-color;
- color: #fff;
- }
-
- &.chatbot {
- align-self: flex-start;
- background-color: $input-background;
- color: $text-color;
- }
-
- span {
- flex-grow: 1;
- padding-right: 10px;
- }
-
- img {
- max-width: 50px;
- max-height: 50px;
- border-radius: 50%;
- }
+ align-items: center;
+ justify-content: center;
+
+ &:hover {
+ background-color: darken($primary-color, 10%);
+ }
+
+ &:disabled {
+ background-color: $light-text-color;
+ cursor: not-allowed;
}
- .follow-up-questions {
- margin-top: 10px;
- width: 100%;
-
- h4 {
- margin-bottom: 5px;
- font-size: 14px;
- }
-
- .follow-up-button {
- background-color: $follow-up-bg-color;
- border: 1px solid #ddd;
- border-radius: 8px;
- padding: 8px 10px;
- margin: 4px 0;
- cursor: pointer;
- transition: background-color 0.3s;
- display: block;
- width: 100%;
- text-align: left;
- white-space: normal;
- word-wrap: break-word;
- font-size: 12px;
- color: $text-color;
- min-height: 40px;
- height: auto;
- line-height: 1.3;
-
- &:hover {
- background-color: $follow-up-hover-bg-color;
- }
- }
+ .spinner {
+ height: 24px;
+ width: 24px;
+ border: 3px solid rgba(255, 255, 255, 0.3);
+ border-top: 3px solid #fff;
+ border-radius: 50%;
+ animation: spin 1s linear infinite;
}
}
}
+}
- .chat-form {
- display: flex;
- flex-grow: 0;
- bottom: 0;
- width: 100%;
- padding: 10px;
- background-color: $input-background;
- box-shadow: inset 0 -1px 2px $shadow-color;
- margin-bottom: 0;
+.message {
+ max-width: 80%;
+ margin-bottom: 20px;
+ padding: 16px 20px;
+ border-radius: 18px;
+ font-size: 15px;
+ line-height: 1.5;
+ box-shadow: 0 2px 4px $shadow-color;
+
+ &.user {
+ align-self: flex-end;
+ background-color: $primary-color;
+ color: white;
+ border-bottom-right-radius: 4px;
+ }
- input[type='text'] {
- flex-grow: 1;
- border: 1px solid darken($input-background, 10%);
- border-radius: $border-radius;
- padding: 8px 12px;
- margin-right: 10px;
+ &.chatbot {
+ align-self: flex-start;
+ background-color: $secondary-color;
+ color: $text-color;
+ border-bottom-left-radius: 4px;
+ }
+
+ .toggle-info {
+ background-color: transparent;
+ color: $primary-color;
+ border: 1px solid $primary-color;
+ width: 100%;
+ height: fit-content;
+ border-radius: 8px;
+ padding: 10px 16px;
+ font-size: 14px;
+ cursor: pointer;
+ transition: $transition;
+ margin-top: 10px;
+
+ &:hover {
+ background-color: rgba($primary-color, 0.1);
}
+ }
+}
- button {
- padding: 8px 16px;
- background-color: $button-color;
- color: #fff;
- border: none;
- border-radius: $border-radius;
- cursor: pointer;
- transition: background-color 0.3s;
- min-width: 80px;
+.follow-up-questions {
+ margin-top: 15px;
- &:hover {
- background-color: $button-hover-color;
- }
+ h4 {
+ font-size: 15px;
+ font-weight: 600;
+ margin-bottom: 10px;
+ }
+
+ .questions-list {
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
+ }
+
+ .follow-up-button {
+ background-color: #fff;
+ color: $primary-color;
+ border: 1px solid $primary-color;
+ border-radius: 8px;
+ padding: 10px 16px;
+ font-size: 14px;
+ cursor: pointer;
+ transition: $transition;
+ text-align: left;
+ white-space: normal;
+ word-wrap: break-word;
+ width: 100%;
+ height: fit-content;
+
+ &:hover {
+ background-color: $primary-color;
+ color: #fff;
}
}
}
-.uploading-overlay {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- background-color: rgba($background-color, 0.95);
- display: flex;
- justify-content: center;
+.citation-button {
+ display: inline-flex;
align-items: center;
- font-size: 1.5em;
+ justify-content: center;
+ width: 20px;
+ height: 20px;
+ border-radius: 50%;
+ background-color: rgba(0, 0, 0, 0.1);
color: $text-color;
- z-index: 10;
-
- &::before {
- content: 'Uploading Docs...';
- font-weight: bold;
+ font-size: 12px;
+ font-weight: bold;
+ margin-left: 5px;
+ cursor: pointer;
+ transition: $transition;
+ vertical-align: middle;
+
+ &:hover {
+ background-color: rgba(0, 0, 0, 0.2);
}
}
-.modal {
- position: fixed;
+.uploading-overlay {
+ position: absolute;
top: 0;
left: 0;
- width: 100%;
- height: 100%;
+ right: 0;
+ bottom: 0;
+ background-color: rgba(255, 255, 255, 0.8);
display: flex;
justify-content: center;
align-items: center;
- background-color: rgba(0, 0, 0, 0.4);
-
- .modal-content {
- background-color: $input-background;
- color: $text-color;
- padding: 20px;
- border-radius: $border-radius;
- box-shadow: 0 2px 10px $shadow-color;
- display: flex;
- flex-direction: column;
- align-items: center;
- width: auto;
- min-width: 300px;
-
- h4 {
- margin-bottom: 15px;
- }
-
- p {
- margin-bottom: 20px;
- }
+ z-index: 1000;
+}
- button {
- padding: 10px 20px;
- background-color: $button-color;
- color: #fff;
- border: none;
- border-radius: $border-radius;
- cursor: pointer;
- transition: background-color 0.3s;
+@keyframes spin {
+ 0% {
+ transform: rotate(0deg);
+ }
+ 100% {
+ transform: rotate(360deg);
+ }
+}
- &:hover {
- background-color: $button-hover-color;
- }
- }
+@media (max-width: 768px) {
+ .chat-box {
+ border-radius: 0;
}
- .thought-text {
- color: #6c757d;
- font-style: italic;
+
+ .message {
+ max-width: 90%;
}
}
diff --git a/src/client/views/nodes/ChatBox/ChatBox.tsx b/src/client/views/nodes/ChatBox/ChatBox.tsx
index 36416a330..4a98f8dc1 100644
--- a/src/client/views/nodes/ChatBox/ChatBox.tsx
+++ b/src/client/views/nodes/ChatBox/ChatBox.tsx
@@ -21,6 +21,8 @@ import { DocumentManager } from '../../../util/DocumentManager';
import { v4 as uuidv4 } from 'uuid';
import { chunk } from 'lodash';
import { DocUtils } from '../../../documents/DocUtils';
+import { createRef } from 'react';
+import { ClientUtils } from '../../../../ClientUtils';
dotenv.config();
@@ -37,10 +39,10 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
@observable private linked_csv_files: { filename: string; id: string; text: string }[] = [];
private openai: OpenAI;
private vectorstore_id: string;
- private documents: AI_Document[] = [];
- private _oldWheel: any;
private vectorstore: Vectorstore;
private agent: Agent; // Add the ChatBot instance
+ private _oldWheel: HTMLDivElement | null = null;
+ private messagesRef: React.RefObject<HTMLDivElement>;
public static LayoutString(fieldKey: string) {
return FieldView.LayoutString(ChatBox, fieldKey);
@@ -59,6 +61,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
}
this.vectorstore = new Vectorstore(this.vectorstore_id, this.retrieveDocIds);
this.agent = new Agent(this.vectorstore, this.retrieveSummaries, this.retrieveFormattedHistory, this.retrieveCSVData, this.addLinkedUrlDoc);
+ this.messagesRef = React.createRef<HTMLDivElement>();
reaction(
() => this.history.map((msg: AssistantMessage) => ({ role: msg.role, content: msg.content, follow_up_questions: msg.follow_up_questions, citations: msg.citations })),
@@ -133,6 +136,23 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
return new OpenAI(configuration);
}
+ addScrollListener = () => {
+ if (this.messagesRef.current) {
+ this.messagesRef.current.addEventListener('wheel', this.onPassiveWheel, { passive: false });
+ }
+ };
+
+ removeScrollListener = () => {
+ if (this.messagesRef.current) {
+ this.messagesRef.current.removeEventListener('wheel', this.onPassiveWheel);
+ }
+ };
+
+ scrollToBottom = () => {
+ if (this.messagesRef.current) {
+ }
+ };
+
onPassiveWheel = (e: WheelEvent) => {
if (this._props.isContentActive()) {
e.stopPropagation();
@@ -160,6 +180,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
this.current_message = { ...this.current_message, processing_info: update };
}
});
+ this.scrollToBottom();
};
const finalMessage = await this.agent.askAgent(trimmedText, onUpdate);
@@ -176,8 +197,10 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
this.history.push({ role: ASSISTANT_ROLE.ASSISTANT, content: [{ index: 0, type: TEXT_TYPE.ERROR, text: 'Sorry, I encountered an error while processing your request.', citation_ids: null }], processing_info: [] });
} finally {
this.isLoading = false;
+ this.scrollToBottom();
}
}
+ this.scrollToBottom();
};
@action
@@ -202,6 +225,11 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
doc.chunk_simpl = JSON.stringify({ chunks: [chunkToAdd] });
};
+ @computed
+ get userName() {
+ return ClientUtils.CurrentUserEmail;
+ }
+
@action
handleCitationClick = (citation: Citation) => {
console.log('Citation clicked:', citation);
@@ -276,6 +304,10 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
return highlight_doc;
};
+ componentDidUpdate() {
+ this.scrollToBottom();
+ }
+
componentDidMount() {
this._props.setContentViewBox?.(this);
if (this.dataDoc.data) {
@@ -332,6 +364,11 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
console.log('Deleted docs: ', change.oldValue);
}
});
+ this.addScrollListener();
+ }
+
+ componentWillUnmount() {
+ this.removeScrollListener();
}
@computed
@@ -411,35 +448,41 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
};
render() {
return (
- <div className="chatBox">
- {this.isUploadingDocs && <div className="uploading-overlay"></div>}
- <div
- className="scroll-box chat-content"
- ref={r => {
- this._oldWheel?.removeEventListener('wheel', this.onPassiveWheel);
- this._oldWheel = r;
- r?.addEventListener('wheel', this.onPassiveWheel, { passive: false });
- }}>
- <div className="messages">
- {this.history.map((message, index) => (
- <MessageComponentBox key={index} message={message} index={index} onFollowUpClick={this.handleFollowUpClick} onCitationClick={this.handleCitationClick} updateMessageCitations={this.updateMessageCitations} />
- ))}
- {!this.current_message ? null : (
- <MessageComponentBox
- key={this.history.length}
- message={this.current_message}
- index={this.history.length}
- onFollowUpClick={this.handleFollowUpClick}
- onCitationClick={this.handleCitationClick}
- updateMessageCitations={this.updateMessageCitations}
- />
- )}
+ <div className="chat-box">
+ {this.isUploadingDocs && (
+ <div className="uploading-overlay">
+ <div className="spinner"></div>
</div>
+ )}
+ <div className="chat-header">
+ <h2>{this.userName()}'s AI Assistant</h2>
</div>
- <form onSubmit={this.askGPT} className="chat-form">
- <input type="text" name="messageInput" autoComplete="off" placeholder="Type a message..." value={this.inputValue} onChange={e => (this.inputValue = e.target.value)} />
- <button type="submit" disabled={this.isLoading}>
- {this.isLoading ? 'Thinking...' : 'Send'}
+ <div className="chat-messages" ref={this.messagesRef}>
+ {this.history.map((message, index) => (
+ <MessageComponentBox key={index} message={message} index={index} onFollowUpClick={this.handleFollowUpClick} onCitationClick={this.handleCitationClick} updateMessageCitations={this.updateMessageCitations} />
+ ))}
+ {this.current_message && (
+ <MessageComponentBox
+ key={this.history.length}
+ message={this.current_message}
+ index={this.history.length}
+ onFollowUpClick={this.handleFollowUpClick}
+ onCitationClick={this.handleCitationClick}
+ updateMessageCitations={this.updateMessageCitations}
+ />
+ )}
+ </div>
+ <form onSubmit={this.askGPT} className="chat-input">
+ <input type="text" name="messageInput" autoComplete="off" placeholder="Type your message here..." value={this.inputValue} onChange={e => (this.inputValue = e.target.value)} />
+ <button className="submit-button" type="submit" disabled={this.isLoading}>
+ {this.isLoading ? (
+ <div className="spinner"></div>
+ ) : (
+ <svg viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" strokeWidth="2" fill="none" strokeLinecap="round" strokeLinejoin="round">
+ <line x1="22" y1="2" x2="11" y2="13"></line>
+ <polygon points="22 2 15 22 11 13 2 9 22 2"></polygon>
+ </svg>
+ )}
</button>
</form>
</div>
diff --git a/src/client/views/nodes/ChatBox/MessageComponent.scss b/src/client/views/nodes/ChatBox/MessageComponent.scss
deleted file mode 100644
index 6fcc0e5e7..000000000
--- a/src/client/views/nodes/ChatBox/MessageComponent.scss
+++ /dev/null
@@ -1,10 +0,0 @@
-MessageComponent-citation {
- color: lightblue;
- vertical-align: super;
- font-size: smaller;
-}
-MessageComponent-file_path {
- color: lightblue;
- vertical-align: baseline;
- font-size: inherit;
-}
diff --git a/src/client/views/nodes/ChatBox/MessageComponent.tsx b/src/client/views/nodes/ChatBox/MessageComponent.tsx
index 0b8fa6b96..00e9795e3 100644
--- a/src/client/views/nodes/ChatBox/MessageComponent.tsx
+++ b/src/client/views/nodes/ChatBox/MessageComponent.tsx
@@ -1,7 +1,7 @@
-import React from 'react';
+import React, { useState } from 'react';
import { observer } from 'mobx-react';
import { AssistantMessage, Citation, MessageContent, PROCESSING_TYPE, ProcessingInfo, TEXT_TYPE } from './types';
-import Markdown from 'react-markdown';
+import ReactMarkdown from 'react-markdown';
interface MessageComponentProps {
message: AssistantMessage;
@@ -12,37 +12,20 @@ interface MessageComponentProps {
}
const MessageComponentBox: React.FC<MessageComponentProps> = function ({ message, index, onFollowUpClick, onCitationClick, updateMessageCitations }) {
+ const [dropdownOpen, setDropdownOpen] = useState(false);
+
const renderContent = (item: MessageContent) => {
const i = item.index;
if (item.type === TEXT_TYPE.GROUNDED) {
const citation_ids = item.citation_ids || [];
return (
<span key={i} className="grounded-text">
- {item.text}
+ <ReactMarkdown>{item.text}</ReactMarkdown>
{citation_ids.map((id, idx) => {
const citation = message.citations?.find(c => c.citation_id === id);
if (!citation) return null;
return (
- <button
- key={i + idx}
- className="citation-button"
- onClick={() => onCitationClick(citation)}
- style={{
- display: 'inline-flex',
- alignItems: 'center',
- justifyContent: 'center',
- width: '20px',
- height: '20px',
- borderRadius: '50%',
- border: 'none',
- background: '#ff6347',
- color: 'white',
- fontSize: '12px',
- fontWeight: 'bold',
- cursor: 'pointer',
- margin: '0 2px',
- padding: 0,
- }}>
+ <button key={i + idx} className="citation-button" onClick={() => onCitationClick(citation)}>
{idx + 1}
</button>
);
@@ -52,49 +35,65 @@ const MessageComponentBox: React.FC<MessageComponentProps> = function ({ message
} else if (item.type === TEXT_TYPE.NORMAL) {
return (
<span key={i} className="normal-text">
- {item.text}
+ <ReactMarkdown>{item.text}</ReactMarkdown>
</span>
);
} else if ('query' in item) {
- // Handle the case where the item has a query property
return (
<span key={i} className="query-text">
- {JSON.stringify(item.query)}
+ <ReactMarkdown>{JSON.stringify(item.query)}</ReactMarkdown>
</span>
);
} else {
- // Fallback for any other unexpected cases
- return <span key={i}>{JSON.stringify(item)}</span>;
+ return (
+ <span key={i}>
+ <ReactMarkdown>{JSON.stringify(item)}</ReactMarkdown>
+ </span>
+ );
}
};
- console.log(message.processing_info);
+ const hasProcessingInfo = message.processing_info && message.processing_info.length > 0;
+
+ const renderProcessingInfo = (info: ProcessingInfo) => {
+ if (info.type === PROCESSING_TYPE.THOUGHT) {
+ return (
+ <div key={info.index} className="dropdown-item">
+ <strong>Thought:</strong> {info.content}
+ </div>
+ );
+ } else if (info.type === PROCESSING_TYPE.ACTION) {
+ return (
+ <div key={info.index} className="dropdown-item">
+ <strong>Action:</strong> {info.content}
+ </div>
+ );
+ } else {
+ return null;
+ }
+ };
return (
<div className={`message ${message.role}`}>
- {message.processing_info &&
- (message.processing_info as ProcessingInfo[]).map(item =>
- item.type === PROCESSING_TYPE.THOUGHT ? (
- <div key={item.index} className="thought">
- <strong>Thought:</strong> {item.content}
- </div>
- ) : item.type === PROCESSING_TYPE.ACTION ? (
- <div key={item.index} className="action">
- <strong>Action:</strong> {item.content}
- </div>
- ) : (
- <div key={item.index} className="error"></div>
- )
- )}
- <div>{message.content && message.content.map(messageFragment => <React.Fragment key={messageFragment.index}>{renderContent(messageFragment)}</React.Fragment>)}</div>
+ <div className="message-content">{message.content && message.content.map(messageFragment => <React.Fragment key={messageFragment.index}>{renderContent(messageFragment)}</React.Fragment>)}</div>
+ {hasProcessingInfo && (
+ <div className="processing-info">
+ <button className="toggle-info" onClick={() => setDropdownOpen(!dropdownOpen)}>
+ {dropdownOpen ? 'Hide Agent Thoughts/Actions' : 'Show Agent Thoughts/Actions'}
+ </button>
+ {dropdownOpen && <div className="info-content">{message.processing_info.map(renderProcessingInfo)}</div>}
+ </div>
+ )}
{message.follow_up_questions && message.follow_up_questions.length > 0 && (
<div className="follow-up-questions">
<h4>Follow-up Questions:</h4>
- {message.follow_up_questions.map((question, idx) => (
- <button key={idx} className="follow-up-button" onClick={() => onFollowUpClick(question)}>
- {question}
- </button>
- ))}
+ <div className="questions-list">
+ {message.follow_up_questions.map((question, idx) => (
+ <button key={idx} className="follow-up-button" onClick={() => onFollowUpClick(question)}>
+ {question}
+ </button>
+ ))}
+ </div>
</div>
)}
</div>
diff --git a/src/server/ApiManagers/AssistantManager.ts b/src/server/ApiManagers/AssistantManager.ts
index cd26ca79b..9b85dbbe8 100644
--- a/src/server/ApiManagers/AssistantManager.ts
+++ b/src/server/ApiManagers/AssistantManager.ts
@@ -14,6 +14,8 @@ import { PartitionResponse } from 'unstructured-client/sdk/models/operations';
import { ChunkingStrategy, Strategy } from 'unstructured-client/sdk/models/shared';
import * as cheerio from 'cheerio';
import { ScrapflyClient, ScrapeConfig } from 'scrapfly-sdk';
+import { google } from 'googleapis';
+import puppeteer from 'puppeteer';
export enum Directory {
parsed_files = 'parsed_files',
@@ -55,6 +57,7 @@ export default class AssistantManager extends ApiManager {
},
});
const scrapflyClient = new ScrapflyClient({ key: process.env._CLIENT_SCRAPFLY_API_KEY! });
+ const customsearch = google.customsearch('v1');
register({
method: Method.POST,
@@ -89,20 +92,18 @@ export default class AssistantManager extends ApiManager {
secureHandler: async ({ req, res }) => {
const { query } = req.body;
try {
- const response = await axios.get('http://api.serpstack.com/search', {
- params: {
- access_key: process.env._CLIENT_SERPSTACK_API_KEY,
- query: query,
- },
+ const response = await customsearch.cse.list({
+ q: query,
+ cx: process.env._CLIENT_GOOGLE_SEARCH_ENGINE_ID,
+ key: process.env._CLIENT_GOOGLE_API_KEY,
+ safe: 'active',
});
- console.log(response.data);
- const results = response.data.organic_results.map((result: any) => ({
- url: result.url,
- snippet: result.snippet,
- }));
-
- console.log(results);
+ const results =
+ response.data.items?.map((item: any) => ({
+ url: item.link,
+ snippet: item.snippet,
+ })) || [];
res.send({ results });
} catch (error: any) {
@@ -144,6 +145,7 @@ export default class AssistantManager extends ApiManager {
const scrapedImagesDirectory = pathToDirectory(Directory.scrape_images);
const filePath = serverPathToFile(Directory.scrape_images, url_filename);
+ // Check if the image already exists
if (fs.existsSync(filePath)) {
const imageBuffer = await readFileAsync(filePath);
const base64Image = imageBuffer.toString('base64');
@@ -151,33 +153,27 @@ export default class AssistantManager extends ApiManager {
return res.send({ website_image_base64: base64Image });
}
+ // Create the directory if it doesn't exist
if (!fs.existsSync(scrapedImagesDirectory)) {
fs.mkdirSync(scrapedImagesDirectory);
}
- const result = await scrapflyClient.scrape(
- new ScrapeConfig({
- url: url,
- render_js: true,
- screenshots: { everything: 'fullpage' },
- })
- );
-
- const screenshotPromises = Object.entries(result.result.screenshots).map(async ([name, screenshot]) => {
- const response = await axios.get(screenshot.url, {
- params: {
- key: process.env._CLIENT_SCRAPFLY_API_KEY!,
- options: 'print_media_format',
- proxy_pool: 'public_residential_pool',
- },
- responseType: 'arraybuffer',
- });
- await fs.promises.writeFile(filePath, response.data);
- return response.data.toString('base64');
+ // Launch Puppeteer to take a screenshot of the webpage
+ const browser = await puppeteer.launch({
+ args: ['--no-sandbox', '--disable-setuid-sandbox'],
});
-
- const base64Screenshots = await Promise.all(screenshotPromises);
- res.send({ website_image_base64: base64Screenshots[0] });
+ const page = await browser.newPage();
+ await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36');
+ await page.goto(url, { waitUntil: 'networkidle2' });
+ const screenshotBuffer = await page.screenshot({ fullPage: true });
+ await browser.close();
+
+ // Save the screenshot to the file system
+ await writeFileAsync(filePath, screenshotBuffer);
+
+ // Return the base64-encoded image
+ const base64Image = Buffer.from(screenshotBuffer).toString('base64');
+ res.send({ website_image_base64: base64Image });
} catch (error: any) {
console.error('Error scraping website:', error);
res.status(500).send({ error: 'Failed to scrape website', details: error.message });