mirror of
https://github.com/danswer-ai/danswer.git
synced 2025-03-17 21:32:36 +01:00
UI for AI thoughts (#385)
This commit is contained in:
parent
06c1afce42
commit
c68afbe9d0
@ -46,27 +46,27 @@ logger = setup_logger()
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("/search-intent")
|
||||
@router.post("/search-intent")
|
||||
def get_search_type(
|
||||
question: QuestionRequest = Depends(), _: User = Depends(current_user)
|
||||
question: QuestionRequest, _: User = Depends(current_user)
|
||||
) -> HelperResponse:
|
||||
query = question.query
|
||||
use_keyword = question.use_keyword if question.use_keyword is not None else False
|
||||
return recommend_search_flow(query, use_keyword)
|
||||
|
||||
|
||||
@router.get("/query-validation")
|
||||
@router.post("/query-validation")
|
||||
def query_validation(
|
||||
question: QuestionRequest = Depends(), _: User = Depends(current_user)
|
||||
question: QuestionRequest, _: User = Depends(current_user)
|
||||
) -> QueryValidationResponse:
|
||||
query = question.query
|
||||
reasoning, answerable = get_query_answerability(query)
|
||||
return QueryValidationResponse(reasoning=reasoning, answerable=answerable)
|
||||
|
||||
|
||||
@router.get("/stream-query-validation")
|
||||
@router.post("/stream-query-validation")
|
||||
def stream_query_validation(
|
||||
question: QuestionRequest = Depends(), _: User = Depends(current_user)
|
||||
question: QuestionRequest, _: User = Depends(current_user)
|
||||
) -> StreamingResponse:
|
||||
query = question.query
|
||||
return StreamingResponse(
|
||||
|
@ -29,6 +29,11 @@ const nextConfig = {
|
||||
destination: "http://127.0.0.1:8080/stream-direct-qa:params*", // Proxy to Backend
|
||||
permanent: true,
|
||||
},
|
||||
{
|
||||
source: "/api/stream-query-validation:params*",
|
||||
destination: "http://127.0.0.1:8080/stream-query-validation:params*", // Proxy to Backend
|
||||
permanent: true,
|
||||
},
|
||||
];
|
||||
},
|
||||
};
|
||||
|
681
web/package-lock.json
generated
681
web/package-lock.json
generated
@ -22,6 +22,7 @@
|
||||
"react-dom": "^18.2.0",
|
||||
"react-dropzone": "^14.2.3",
|
||||
"react-icons": "^4.8.0",
|
||||
"react-loader-spinner": "^5.4.5",
|
||||
"semver": "^7.5.4",
|
||||
"swr": "^2.1.5",
|
||||
"tailwindcss": "^3.3.1",
|
||||
@ -54,6 +55,453 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@ampproject/remapping": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz",
|
||||
"integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@jridgewell/gen-mapping": "^0.3.0",
|
||||
"@jridgewell/trace-mapping": "^0.3.9"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
"version": "7.22.13",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
|
||||
"integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
|
||||
"dependencies": {
|
||||
"@babel/highlight": "^7.22.13",
|
||||
"chalk": "^2.4.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame/node_modules/ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"dependencies": {
|
||||
"color-convert": "^1.9.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame/node_modules/chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"supports-color": "^5.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame/node_modules/color-convert": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||
"dependencies": {
|
||||
"color-name": "1.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame/node_modules/color-name": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
|
||||
},
|
||||
"node_modules/@babel/code-frame/node_modules/escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame/node_modules/has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame/node_modules/supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"dependencies": {
|
||||
"has-flag": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/compat-data": {
|
||||
"version": "7.22.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz",
|
||||
"integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/core": {
|
||||
"version": "7.22.11",
|
||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.11.tgz",
|
||||
"integrity": "sha512-lh7RJrtPdhibbxndr6/xx0w8+CVlY5FJZiaSz908Fpy+G0xkBFTvwLcKJFF4PJxVfGhVWNebikpWGnOoC71juQ==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@ampproject/remapping": "^2.2.0",
|
||||
"@babel/code-frame": "^7.22.10",
|
||||
"@babel/generator": "^7.22.10",
|
||||
"@babel/helper-compilation-targets": "^7.22.10",
|
||||
"@babel/helper-module-transforms": "^7.22.9",
|
||||
"@babel/helpers": "^7.22.11",
|
||||
"@babel/parser": "^7.22.11",
|
||||
"@babel/template": "^7.22.5",
|
||||
"@babel/traverse": "^7.22.11",
|
||||
"@babel/types": "^7.22.11",
|
||||
"convert-source-map": "^1.7.0",
|
||||
"debug": "^4.1.0",
|
||||
"gensync": "^1.0.0-beta.2",
|
||||
"json5": "^2.2.3",
|
||||
"semver": "^6.3.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/babel"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/core/node_modules/json5": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
|
||||
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"json5": "lib/cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/core/node_modules/semver": {
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/generator": {
|
||||
"version": "7.22.10",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.10.tgz",
|
||||
"integrity": "sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==",
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.22.10",
|
||||
"@jridgewell/gen-mapping": "^0.3.2",
|
||||
"@jridgewell/trace-mapping": "^0.3.17",
|
||||
"jsesc": "^2.5.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-annotate-as-pure": {
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz",
|
||||
"integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==",
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.22.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-compilation-targets": {
|
||||
"version": "7.22.10",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.10.tgz",
|
||||
"integrity": "sha512-JMSwHD4J7SLod0idLq5PKgI+6g/hLD/iuWBq08ZX49xE14VpVEojJ5rHWptpirV2j020MvypRLAXAO50igCJ5Q==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/compat-data": "^7.22.9",
|
||||
"@babel/helper-validator-option": "^7.22.5",
|
||||
"browserslist": "^4.21.9",
|
||||
"lru-cache": "^5.1.1",
|
||||
"semver": "^6.3.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
|
||||
"integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"yallist": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-compilation-targets/node_modules/semver": {
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-compilation-targets/node_modules/yallist": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
|
||||
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/@babel/helper-environment-visitor": {
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz",
|
||||
"integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-function-name": {
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz",
|
||||
"integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==",
|
||||
"dependencies": {
|
||||
"@babel/template": "^7.22.5",
|
||||
"@babel/types": "^7.22.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-hoist-variables": {
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz",
|
||||
"integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==",
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.22.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-module-imports": {
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz",
|
||||
"integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==",
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.22.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-module-transforms": {
|
||||
"version": "7.22.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz",
|
||||
"integrity": "sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/helper-environment-visitor": "^7.22.5",
|
||||
"@babel/helper-module-imports": "^7.22.5",
|
||||
"@babel/helper-simple-access": "^7.22.5",
|
||||
"@babel/helper-split-export-declaration": "^7.22.6",
|
||||
"@babel/helper-validator-identifier": "^7.22.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-plugin-utils": {
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
|
||||
"integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-simple-access": {
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz",
|
||||
"integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.22.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-split-export-declaration": {
|
||||
"version": "7.22.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
|
||||
"integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.22.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-string-parser": {
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz",
|
||||
"integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-validator-identifier": {
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz",
|
||||
"integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-validator-option": {
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz",
|
||||
"integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helpers": {
|
||||
"version": "7.22.11",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.11.tgz",
|
||||
"integrity": "sha512-vyOXC8PBWaGc5h7GMsNx68OH33cypkEDJCHvYVVgVbbxJDROYVtexSk0gK5iCF1xNjRIN2s8ai7hwkWDq5szWg==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/template": "^7.22.5",
|
||||
"@babel/traverse": "^7.22.11",
|
||||
"@babel/types": "^7.22.11"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/highlight": {
|
||||
"version": "7.22.13",
|
||||
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.13.tgz",
|
||||
"integrity": "sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==",
|
||||
"dependencies": {
|
||||
"@babel/helper-validator-identifier": "^7.22.5",
|
||||
"chalk": "^2.4.2",
|
||||
"js-tokens": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/highlight/node_modules/ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"dependencies": {
|
||||
"color-convert": "^1.9.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/highlight/node_modules/chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"supports-color": "^5.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/highlight/node_modules/color-convert": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||
"dependencies": {
|
||||
"color-name": "1.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/highlight/node_modules/color-name": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
|
||||
},
|
||||
"node_modules/@babel/highlight/node_modules/escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/highlight/node_modules/has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/highlight/node_modules/supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"dependencies": {
|
||||
"has-flag": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/parser": {
|
||||
"version": "7.22.14",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.14.tgz",
|
||||
"integrity": "sha512-1KucTHgOvaw/LzCVrEOAyXkr9rQlp0A1HiHRYnSUE9dmb8PvPW7o5sscg+5169r54n3vGlbx6GevTE/Iw/P3AQ==",
|
||||
"bin": {
|
||||
"parser": "bin/babel-parser.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/plugin-syntax-jsx": {
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz",
|
||||
"integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==",
|
||||
"dependencies": {
|
||||
"@babel/helper-plugin-utils": "^7.22.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/runtime": {
|
||||
"version": "7.22.11",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.11.tgz",
|
||||
@ -66,6 +514,83 @@
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/template": {
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz",
|
||||
"integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==",
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.22.5",
|
||||
"@babel/parser": "^7.22.5",
|
||||
"@babel/types": "^7.22.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/traverse": {
|
||||
"version": "7.22.11",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.11.tgz",
|
||||
"integrity": "sha512-mzAenteTfomcB7mfPtyi+4oe5BZ6MXxWcn4CX+h4IRJ+OOGXBrWU6jDQavkQI9Vuc5P+donFabBfFCcmWka9lQ==",
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.22.10",
|
||||
"@babel/generator": "^7.22.10",
|
||||
"@babel/helper-environment-visitor": "^7.22.5",
|
||||
"@babel/helper-function-name": "^7.22.5",
|
||||
"@babel/helper-hoist-variables": "^7.22.5",
|
||||
"@babel/helper-split-export-declaration": "^7.22.6",
|
||||
"@babel/parser": "^7.22.11",
|
||||
"@babel/types": "^7.22.11",
|
||||
"debug": "^4.1.0",
|
||||
"globals": "^11.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/traverse/node_modules/globals": {
|
||||
"version": "11.12.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
|
||||
"integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/types": {
|
||||
"version": "7.22.11",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.11.tgz",
|
||||
"integrity": "sha512-siazHiGuZRz9aB9NpHy9GOs9xiQPKnMzgdr493iI1M67vRXpnEq8ZOOKzezC5q7zwuQ6sDhdSp4SD9ixKSqKZg==",
|
||||
"dependencies": {
|
||||
"@babel/helper-string-parser": "^7.22.5",
|
||||
"@babel/helper-validator-identifier": "^7.22.5",
|
||||
"to-fast-properties": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@emotion/is-prop-valid": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz",
|
||||
"integrity": "sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==",
|
||||
"dependencies": {
|
||||
"@emotion/memoize": "^0.8.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@emotion/memoize": {
|
||||
"version": "0.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz",
|
||||
"integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA=="
|
||||
},
|
||||
"node_modules/@emotion/stylis": {
|
||||
"version": "0.8.5",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz",
|
||||
"integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ=="
|
||||
},
|
||||
"node_modules/@emotion/unitless": {
|
||||
"version": "0.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz",
|
||||
"integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg=="
|
||||
},
|
||||
"node_modules/@eslint-community/eslint-utils": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
|
||||
@ -867,6 +1392,21 @@
|
||||
"dequal": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/babel-plugin-styled-components": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.1.4.tgz",
|
||||
"integrity": "sha512-Xgp9g+A/cG47sUyRwwYxGM4bR/jDRg5N6it/8+HxCnbT5XNKSKDT9xm4oag/osgqjC2It/vH0yXsomOG6k558g==",
|
||||
"dependencies": {
|
||||
"@babel/helper-annotate-as-pure": "^7.22.5",
|
||||
"@babel/helper-module-imports": "^7.22.5",
|
||||
"@babel/plugin-syntax-jsx": "^7.22.5",
|
||||
"lodash": "^4.17.21",
|
||||
"picomatch": "^2.3.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"styled-components": ">= 2"
|
||||
}
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
@ -972,6 +1512,14 @@
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/camelize": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz",
|
||||
"integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001524",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001524.tgz",
|
||||
@ -1080,6 +1628,12 @@
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
|
||||
},
|
||||
"node_modules/convert-source-map": {
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
|
||||
"integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
||||
@ -1094,6 +1648,24 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/css-color-keywords": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz",
|
||||
"integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/css-to-react-native": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz",
|
||||
"integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==",
|
||||
"dependencies": {
|
||||
"camelize": "^1.0.0",
|
||||
"css-color-keywords": "^1.0.0",
|
||||
"postcss-value-parser": "^4.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/cssesc": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
|
||||
@ -1120,7 +1692,6 @@
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ms": "2.1.2"
|
||||
},
|
||||
@ -1999,6 +2570,15 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/gensync": {
|
||||
"version": "1.0.0-beta.2",
|
||||
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
|
||||
"integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/get-intrinsic": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz",
|
||||
@ -2680,6 +3260,17 @@
|
||||
"js-yaml": "bin/js-yaml.js"
|
||||
}
|
||||
},
|
||||
"node_modules/jsesc": {
|
||||
"version": "2.5.2",
|
||||
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
|
||||
"integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
|
||||
"bin": {
|
||||
"jsesc": "bin/jsesc"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/json-buffer": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
|
||||
@ -2871,8 +3462,7 @@
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"dev": true
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"node_modules/mz": {
|
||||
"version": "2.7.0",
|
||||
@ -3509,6 +4099,25 @@
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||
},
|
||||
"node_modules/react-loader-spinner": {
|
||||
"version": "5.4.5",
|
||||
"resolved": "https://registry.npmjs.org/react-loader-spinner/-/react-loader-spinner-5.4.5.tgz",
|
||||
"integrity": "sha512-32f+sb/v2tnNfyvnCCOS4fpyVHsGXjSyNo6QLniHcaj1XjKLxx14L2z0h6szRugOL8IEJ+53GPwNAdbkDqmy4g==",
|
||||
"dependencies": {
|
||||
"react-is": "^18.2.0",
|
||||
"styled-components": "^5.3.5",
|
||||
"styled-tools": "^1.7.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.0.0 || ^17.0.0 || ^18.0.0",
|
||||
"react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-loader-spinner/node_modules/react-is": {
|
||||
"version": "18.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
|
||||
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
|
||||
},
|
||||
"node_modules/read-cache": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
|
||||
@ -3705,6 +4314,11 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/shallowequal": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz",
|
||||
"integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ=="
|
||||
},
|
||||
"node_modules/shebang-command": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||
@ -3862,6 +4476,54 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/styled-components": {
|
||||
"version": "5.3.11",
|
||||
"resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.11.tgz",
|
||||
"integrity": "sha512-uuzIIfnVkagcVHv9nE0VPlHPSCmXIUGKfJ42LNjxCCTDTL5sgnJ8Z7GZBq0EnLYGln77tPpEpExt2+qa+cZqSw==",
|
||||
"dependencies": {
|
||||
"@babel/helper-module-imports": "^7.0.0",
|
||||
"@babel/traverse": "^7.4.5",
|
||||
"@emotion/is-prop-valid": "^1.1.0",
|
||||
"@emotion/stylis": "^0.8.4",
|
||||
"@emotion/unitless": "^0.7.4",
|
||||
"babel-plugin-styled-components": ">= 1.12.0",
|
||||
"css-to-react-native": "^3.0.0",
|
||||
"hoist-non-react-statics": "^3.0.0",
|
||||
"shallowequal": "^1.1.0",
|
||||
"supports-color": "^5.5.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/styled-components"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">= 16.8.0",
|
||||
"react-dom": ">= 16.8.0",
|
||||
"react-is": ">= 16.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/styled-components/node_modules/has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/styled-components/node_modules/supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"dependencies": {
|
||||
"has-flag": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/styled-jsx": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz",
|
||||
@ -3884,6 +4546,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/styled-tools": {
|
||||
"version": "1.7.2",
|
||||
"resolved": "https://registry.npmjs.org/styled-tools/-/styled-tools-1.7.2.tgz",
|
||||
"integrity": "sha512-IjLxzM20RMwAsx8M1QoRlCG/Kmq8lKzCGyospjtSXt/BTIIcvgTonaxQAsKnBrsZNwhpHzO9ADx5te0h76ILVg=="
|
||||
},
|
||||
"node_modules/sucrase": {
|
||||
"version": "3.34.0",
|
||||
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.34.0.tgz",
|
||||
@ -4039,6 +4706,14 @@
|
||||
"resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
|
||||
"integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA=="
|
||||
},
|
||||
"node_modules/to-fast-properties": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
|
||||
"integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
|
@ -23,6 +23,7 @@
|
||||
"react-dom": "^18.2.0",
|
||||
"react-dropzone": "^14.2.3",
|
||||
"react-icons": "^4.8.0",
|
||||
"react-loader-spinner": "^5.4.5",
|
||||
"semver": "^7.5.4",
|
||||
"swr": "^2.1.5",
|
||||
"tailwindcss": "^3.3.1",
|
||||
@ -30,8 +31,8 @@
|
||||
"yup": "^1.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"prettier": "2.8.8",
|
||||
"eslint": "^8.48.0",
|
||||
"eslint-config-next": "^13.4.9"
|
||||
"eslint-config-next": "^13.4.9",
|
||||
"prettier": "2.8.8"
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,12 @@ import {
|
||||
FiGlobe,
|
||||
FiThumbsDown,
|
||||
FiThumbsUp,
|
||||
FiChevronDown,
|
||||
FiChevronUp,
|
||||
FiAlertCircle,
|
||||
FiChevronRight,
|
||||
FiChevronLeft,
|
||||
FiAlertTriangle,
|
||||
} from "react-icons/fi";
|
||||
import { SiBookstack } from "react-icons/si";
|
||||
import Image from "next/image";
|
||||
@ -172,6 +178,34 @@ export const ChevronsDownIcon = ({
|
||||
return <FiChevronsDown size={size} className={className} />;
|
||||
};
|
||||
|
||||
export const ChevronUpIcon = ({
|
||||
size = 16,
|
||||
className = defaultTailwindCSS,
|
||||
}: IconProps) => {
|
||||
return <FiChevronUp size={size} className={className} />;
|
||||
};
|
||||
|
||||
export const ChevronDownIcon = ({
|
||||
size = 16,
|
||||
className = defaultTailwindCSS,
|
||||
}: IconProps) => {
|
||||
return <FiChevronDown size={size} className={className} />;
|
||||
};
|
||||
|
||||
export const ChevronRightIcon = ({
|
||||
size = 16,
|
||||
className = defaultTailwindCSS,
|
||||
}: IconProps) => {
|
||||
return <FiChevronRight size={size} className={className} />;
|
||||
};
|
||||
|
||||
export const ChevronLeftIcon = ({
|
||||
size = 16,
|
||||
className = defaultTailwindCSS,
|
||||
}: IconProps) => {
|
||||
return <FiChevronLeft size={size} className={className} />;
|
||||
};
|
||||
|
||||
export const CheckmarkIcon = ({
|
||||
size = 16,
|
||||
className = defaultTailwindCSS,
|
||||
@ -179,6 +213,20 @@ export const CheckmarkIcon = ({
|
||||
return <FiCheck size={size} className={className} />;
|
||||
};
|
||||
|
||||
export const AlertIcon = ({
|
||||
size = 16,
|
||||
className = defaultTailwindCSS,
|
||||
}: IconProps) => {
|
||||
return <FiAlertCircle size={size} className={className} />;
|
||||
};
|
||||
|
||||
export const TriangleAlertIcon = ({
|
||||
size = 16,
|
||||
className = defaultTailwindCSS,
|
||||
}: IconProps) => {
|
||||
return <FiAlertTriangle size={size} className={className} />;
|
||||
};
|
||||
|
||||
//
|
||||
// COMPANY LOGOS
|
||||
//
|
||||
|
@ -1,16 +1,24 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { getSourceIcon } from "../source";
|
||||
import { LoadingAnimation } from "../Loading";
|
||||
import { InfoIcon } from "../icons/icons";
|
||||
import {
|
||||
DanswerDocument,
|
||||
SearchResponse,
|
||||
Quote,
|
||||
FlowType,
|
||||
SearchDefaultOverrides,
|
||||
ValidQuestionResponse,
|
||||
} from "@/lib/search/interfaces";
|
||||
import { QAFeedbackBlock } from "./QAFeedback";
|
||||
import { DocumentDisplay } from "./DocumentDisplay";
|
||||
import { ResponseSection, StatusOptions } from "./results/ResponseSection";
|
||||
import { QuotesSection } from "./results/QuotesSection";
|
||||
import { AnswerSection } from "./results/AnswerSection";
|
||||
import {
|
||||
getAIThoughtsIsOpenSavedValue,
|
||||
setAIThoughtsIsOpenSavedValue,
|
||||
} from "@/lib/search/aiThoughtUtils";
|
||||
import { Grid, ThreeDots } from "react-loader-spinner";
|
||||
|
||||
const removeDuplicateDocs = (documents: DanswerDocument[]) => {
|
||||
const seen = new Set<string>();
|
||||
@ -26,15 +34,25 @@ const removeDuplicateDocs = (documents: DanswerDocument[]) => {
|
||||
|
||||
interface SearchResultsDisplayProps {
|
||||
searchResponse: SearchResponse | null;
|
||||
validQuestionResponse: ValidQuestionResponse;
|
||||
isFetching: boolean;
|
||||
defaultOverrides: SearchDefaultOverrides;
|
||||
}
|
||||
|
||||
export const SearchResultsDisplay: React.FC<SearchResultsDisplayProps> = ({
|
||||
searchResponse,
|
||||
validQuestionResponse,
|
||||
isFetching,
|
||||
defaultOverrides,
|
||||
}) => {
|
||||
const [isAIThoughtsOpen, setIsAIThoughtsOpen] = React.useState<boolean>(
|
||||
getAIThoughtsIsOpenSavedValue()
|
||||
);
|
||||
const handleAIThoughtToggle = (newAIThoughtsOpenValue: boolean) => {
|
||||
setAIThoughtsIsOpenSavedValue(newAIThoughtsOpenValue);
|
||||
setIsAIThoughtsOpen(newAIThoughtsOpenValue);
|
||||
};
|
||||
|
||||
if (!searchResponse) {
|
||||
return null;
|
||||
}
|
||||
@ -45,7 +63,16 @@ export const SearchResultsDisplay: React.FC<SearchResultsDisplayProps> = ({
|
||||
return (
|
||||
<div className="flex">
|
||||
<div className="mx-auto">
|
||||
<LoadingAnimation />
|
||||
<ThreeDots
|
||||
height="30"
|
||||
width="40"
|
||||
color="#3b82f6"
|
||||
ariaLabel="grid-loading"
|
||||
radius="12.5"
|
||||
wrapperStyle={{}}
|
||||
wrapperClass=""
|
||||
visible={true}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@ -70,81 +97,63 @@ export const SearchResultsDisplay: React.FC<SearchResultsDisplayProps> = ({
|
||||
searchResponse.suggestedFlowType === FlowType.QUESTION_ANSWER ||
|
||||
defaultOverrides.forceDisplayQA;
|
||||
|
||||
let answerDisplay = <LoadingAnimation text="" size="text-sm" />;
|
||||
if (error) {
|
||||
answerDisplay = (
|
||||
<div className="flex">
|
||||
<InfoIcon
|
||||
size={20}
|
||||
className="text-red-500 my-auto flex flex-shrink-0"
|
||||
/>
|
||||
<div className="text-red-500 text-sm my-auto ml-1">{error}</div>
|
||||
</div>
|
||||
);
|
||||
} else if (answer) {
|
||||
answerDisplay = <p className="mb-4">{answer}</p>;
|
||||
} else if (!isFetching) {
|
||||
answerDisplay = (
|
||||
<div className="text-sm my-auto text-gray-300">Information not found</div>
|
||||
);
|
||||
let questionValidityCheckStatus: StatusOptions = "in-progress";
|
||||
if (validQuestionResponse.answerable) {
|
||||
questionValidityCheckStatus = "success";
|
||||
} else if (validQuestionResponse.answerable === false) {
|
||||
questionValidityCheckStatus = "failed";
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{shouldDisplayQA && (
|
||||
<div className="min-h-[14rem]">
|
||||
<div className="p-4 border-2 rounded-md border-gray-700">
|
||||
<div className="min-h-[16rem] p-4 border-2 rounded-md border-gray-700 relative">
|
||||
<div>
|
||||
<div className="flex mb-1">
|
||||
<h2 className="text font-bold my-auto">AI Answer</h2>
|
||||
<h2 className="text font-bold my-auto mb-1 w-full">AI Answer</h2>
|
||||
</div>
|
||||
|
||||
<div className="mb-2 w-full">
|
||||
<ResponseSection
|
||||
status={questionValidityCheckStatus}
|
||||
header={
|
||||
validQuestionResponse.answerable === null ? (
|
||||
<div className="flex ml-2">Evaluating question...</div>
|
||||
) : (
|
||||
<div className="flex ml-2">AI thoughts</div>
|
||||
)
|
||||
}
|
||||
body={<div>{validQuestionResponse.reasoning}</div>}
|
||||
desiredOpenStatus={isAIThoughtsOpen}
|
||||
setDesiredOpenStatus={handleAIThoughtToggle}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="mb-2 pt-1 border-t border-gray-700 w-full">
|
||||
<AnswerSection
|
||||
answer={answer}
|
||||
quotes={quotes}
|
||||
error={error}
|
||||
isAnswerable={validQuestionResponse.answerable}
|
||||
isFetching={isFetching}
|
||||
aiThoughtsIsOpen={isAIThoughtsOpen}
|
||||
/>
|
||||
</div>
|
||||
{answerDisplay}
|
||||
|
||||
{quotes !== null && answer && (
|
||||
<>
|
||||
<h2 className="text-sm font-bold">Sources</h2>
|
||||
{isFetching && dedupedQuotes.length === 0 ? (
|
||||
<LoadingAnimation text="Finding quotes" size="text-sm" />
|
||||
) : (
|
||||
<div className="flex flex-wrap">
|
||||
{dedupedQuotes.length > 0 ? (
|
||||
dedupedQuotes.map((quoteInfo) => (
|
||||
<a
|
||||
key={quoteInfo.document_id}
|
||||
className="p-2 ml-1 mt-2 border border-gray-800 rounded-lg text-sm flex max-w-[280px] hover:bg-gray-800"
|
||||
href={quoteInfo.link || undefined}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{getSourceIcon(quoteInfo.source_type, 20)}
|
||||
<p className="truncate break-all ml-2">
|
||||
{quoteInfo.semantic_identifier ||
|
||||
quoteInfo.document_id}
|
||||
</p>
|
||||
</a>
|
||||
))
|
||||
) : (
|
||||
<div className="flex">
|
||||
<InfoIcon
|
||||
size={20}
|
||||
className="text-red-500 my-auto flex flex-shrink-0"
|
||||
/>
|
||||
<div className="text-red-500 text-sm my-auto ml-1">
|
||||
Did not find any exact quotes to support the above
|
||||
answer.
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="pt-1 border-t border-gray-700 w-full">
|
||||
<QuotesSection
|
||||
quotes={dedupedQuotes}
|
||||
isFetching={isFetching}
|
||||
isAnswerable={validQuestionResponse.answerable}
|
||||
/>
|
||||
|
||||
{searchResponse.queryEventId !== null && (
|
||||
<div className="ml-auto mt-auto">
|
||||
<QAFeedbackBlock
|
||||
queryId={searchResponse.queryEventId}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{searchResponse.queryEventId !== null && (
|
||||
<div className="absolute right-3 bottom-3">
|
||||
<QAFeedbackBlock queryId={searchResponse.queryEventId} />
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -15,6 +15,7 @@ import {
|
||||
SearchType,
|
||||
SearchDefaultOverrides,
|
||||
SearchRequestOverrides,
|
||||
ValidQuestionResponse,
|
||||
} from "@/lib/search/interfaces";
|
||||
import { searchRequestStreamed } from "@/lib/search/streamingQa";
|
||||
import Cookies from "js-cookie";
|
||||
@ -22,12 +23,19 @@ import { SearchHelper } from "./SearchHelper";
|
||||
import { CancellationToken, cancellable } from "@/lib/search/cancellable";
|
||||
import { NEXT_PUBLIC_DISABLE_STREAMING } from "@/lib/constants";
|
||||
import { searchRequest } from "@/lib/search/qa";
|
||||
import { useObjectState } from "@/lib/hooks";
|
||||
import { questionValidationStreamed } from "@/lib/search/streamingQuestionValidation";
|
||||
|
||||
const SEARCH_DEFAULT_OVERRIDES_START: SearchDefaultOverrides = {
|
||||
forceDisplayQA: false,
|
||||
offset: 0,
|
||||
};
|
||||
|
||||
const VALID_QUESTION_RESPONSE_DEFAULT: ValidQuestionResponse = {
|
||||
reasoning: null,
|
||||
answerable: null,
|
||||
};
|
||||
|
||||
interface SearchSectionProps {
|
||||
connectors: Connector<any>[];
|
||||
defaultSearchType: SearchType;
|
||||
@ -46,6 +54,9 @@ export const SearchSection: React.FC<SearchSectionProps> = ({
|
||||
);
|
||||
const [isFetching, setIsFetching] = useState(false);
|
||||
|
||||
const [validQuestionResponse, setValidQuestionResponse] =
|
||||
useObjectState<ValidQuestionResponse>(VALID_QUESTION_RESPONSE_DEFAULT);
|
||||
|
||||
// Filters
|
||||
const [sources, setSources] = useState<Source[]>([]);
|
||||
|
||||
@ -116,11 +127,12 @@ export const SearchSection: React.FC<SearchSectionProps> = ({
|
||||
|
||||
setIsFetching(true);
|
||||
setSearchResponse(initialSearchResponse);
|
||||
setValidQuestionResponse(VALID_QUESTION_RESPONSE_DEFAULT);
|
||||
|
||||
const searchFn = NEXT_PUBLIC_DISABLE_STREAMING
|
||||
? searchRequest
|
||||
: searchRequestStreamed;
|
||||
await searchFn({
|
||||
const searchFnArgs = {
|
||||
query,
|
||||
sources,
|
||||
updateCurrentAnswer: cancellable({
|
||||
@ -153,7 +165,17 @@ export const SearchSection: React.FC<SearchSectionProps> = ({
|
||||
}),
|
||||
selectedSearchType: searchType ?? selectedSearchType,
|
||||
offset: offset ?? defaultOverrides.offset,
|
||||
});
|
||||
};
|
||||
|
||||
const questionValidationArgs = {
|
||||
query,
|
||||
update: setValidQuestionResponse,
|
||||
};
|
||||
|
||||
await Promise.all([
|
||||
searchFn(searchFnArgs),
|
||||
questionValidationStreamed(questionValidationArgs),
|
||||
]);
|
||||
|
||||
setIsFetching(false);
|
||||
};
|
||||
@ -213,6 +235,7 @@ export const SearchSection: React.FC<SearchSectionProps> = ({
|
||||
<div className="mt-2">
|
||||
<SearchResultsDisplay
|
||||
searchResponse={searchResponse}
|
||||
validQuestionResponse={validQuestionResponse}
|
||||
isFetching={isFetching}
|
||||
defaultOverrides={defaultOverrides}
|
||||
/>
|
||||
|
84
web/src/components/search/results/AnswerSection.tsx
Normal file
84
web/src/components/search/results/AnswerSection.tsx
Normal file
@ -0,0 +1,84 @@
|
||||
import { Quote } from "@/lib/search/interfaces";
|
||||
import { ResponseSection, StatusOptions } from "./ResponseSection";
|
||||
|
||||
interface AnswerSectionProps {
|
||||
answer: string | null;
|
||||
quotes: Quote[] | null;
|
||||
error: string | null;
|
||||
isAnswerable: boolean | null;
|
||||
isFetching: boolean;
|
||||
aiThoughtsIsOpen: boolean;
|
||||
}
|
||||
|
||||
const AnswerHeader = ({
|
||||
answer,
|
||||
error,
|
||||
quotes,
|
||||
isAnswerable,
|
||||
isFetching,
|
||||
}: AnswerSectionProps) => {
|
||||
if (error) {
|
||||
return <>Error while building answer</>;
|
||||
} else if ((answer && quotes !== null) || !isFetching) {
|
||||
if (isAnswerable === false) {
|
||||
return <>Best effort AI answer</>;
|
||||
}
|
||||
return <>AI answer</>;
|
||||
}
|
||||
if (isAnswerable === false) {
|
||||
return <>Building best effort AI answer...</>;
|
||||
}
|
||||
return <>Building answer...</>;
|
||||
};
|
||||
|
||||
const AnswerBody = ({ answer, error, isFetching }: AnswerSectionProps) => {
|
||||
if (error) {
|
||||
return (
|
||||
<div className="flex">
|
||||
<div className="text-red-500 my-auto ml-1">{error}</div>
|
||||
</div>
|
||||
);
|
||||
} else if (answer) {
|
||||
return <p className="">{answer}</p>;
|
||||
} else if (!isFetching) {
|
||||
return <div className="text-gray-300">Information not found</div>;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
export const AnswerSection = (props: AnswerSectionProps) => {
|
||||
let status = "in-progress" as StatusOptions;
|
||||
if (props.error) {
|
||||
status = "failed";
|
||||
}
|
||||
// if AI thoughts is visible, don't mark this as a success until that section
|
||||
// is complete
|
||||
else if (!props.aiThoughtsIsOpen || props.isAnswerable !== null) {
|
||||
if (props.isAnswerable === false) {
|
||||
status = "warning";
|
||||
} else if ((props.quotes !== null && props.answer) || !props.isFetching) {
|
||||
status = "success";
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<ResponseSection
|
||||
status={status}
|
||||
header={
|
||||
<div className="flex">
|
||||
<div className="ml-2">{<AnswerHeader {...props} />}</div>
|
||||
</div>
|
||||
}
|
||||
body={
|
||||
<div className="">
|
||||
<AnswerBody {...props} />
|
||||
</div>
|
||||
}
|
||||
desiredOpenStatus={
|
||||
props.aiThoughtsIsOpen ? props.isAnswerable !== null : true
|
||||
}
|
||||
isNotControllable={true}
|
||||
/>
|
||||
);
|
||||
};
|
82
web/src/components/search/results/QuotesSection.tsx
Normal file
82
web/src/components/search/results/QuotesSection.tsx
Normal file
@ -0,0 +1,82 @@
|
||||
import { Quote } from "@/lib/search/interfaces";
|
||||
import { ResponseSection, StatusOptions } from "./ResponseSection";
|
||||
import { getSourceIcon } from "@/components/source";
|
||||
|
||||
interface QuotesSectionProps {
|
||||
quotes: Quote[] | null;
|
||||
isAnswerable: boolean | null;
|
||||
isFetching: boolean;
|
||||
}
|
||||
|
||||
const QuotesHeader = ({ quotes, isFetching }: QuotesSectionProps) => {
|
||||
if ((!quotes || quotes.length === 0) && isFetching) {
|
||||
return <>Extracting quotes...</>;
|
||||
}
|
||||
|
||||
if (!quotes || quotes.length === 0) {
|
||||
return <>No quotes found</>;
|
||||
}
|
||||
|
||||
return <>Quotes</>;
|
||||
};
|
||||
|
||||
const QuotesBody = ({ quotes, isFetching }: QuotesSectionProps) => {
|
||||
if (!quotes && isFetching) {
|
||||
// height of quotes section to avoid extra "jumps" from the quotes loading
|
||||
return <div className="h-[42px]"></div>;
|
||||
}
|
||||
|
||||
if (!isFetching && (!quotes || !quotes.length)) {
|
||||
return (
|
||||
<div className="flex">
|
||||
<div className="text-red-500 text-sm my-auto">
|
||||
Did not find any exact quotes to support the above answer.
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-wrap">
|
||||
{quotes!.map((quoteInfo) => (
|
||||
<a
|
||||
key={quoteInfo.document_id}
|
||||
className="p-2 mr-1 border border-gray-800 rounded-lg text-sm flex max-w-[280px] hover:bg-gray-800 w-fit"
|
||||
href={quoteInfo.link || undefined}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{getSourceIcon(quoteInfo.source_type, 20)}
|
||||
<p className="truncate break-all ml-2 mr-1">
|
||||
{quoteInfo.semantic_identifier || quoteInfo.document_id}
|
||||
</p>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const QuotesSection = (props: QuotesSectionProps) => {
|
||||
let status: StatusOptions = "in-progress";
|
||||
if (!props.isFetching) {
|
||||
if (props.quotes && props.quotes.length > 0) {
|
||||
if (props.isAnswerable === false) {
|
||||
status = "warning";
|
||||
} else {
|
||||
status = "success";
|
||||
}
|
||||
} else {
|
||||
status = "failed";
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<ResponseSection
|
||||
status={status}
|
||||
header={<div className="ml-2">{<QuotesHeader {...props} />}</div>}
|
||||
body={<QuotesBody {...props} />}
|
||||
desiredOpenStatus={true}
|
||||
isNotControllable={true}
|
||||
/>
|
||||
);
|
||||
};
|
101
web/src/components/search/results/ResponseSection.tsx
Normal file
101
web/src/components/search/results/ResponseSection.tsx
Normal file
@ -0,0 +1,101 @@
|
||||
import {
|
||||
AlertIcon,
|
||||
CheckmarkIcon,
|
||||
ChevronDownIcon,
|
||||
ChevronLeftIcon,
|
||||
TriangleAlertIcon,
|
||||
} from "@/components/icons/icons";
|
||||
import { useState } from "react";
|
||||
import { Grid } from "react-loader-spinner";
|
||||
|
||||
export type StatusOptions = "in-progress" | "failed" | "warning" | "success";
|
||||
|
||||
interface ResponseSectionProps {
|
||||
header: JSX.Element | string;
|
||||
body: JSX.Element | string;
|
||||
status: StatusOptions;
|
||||
desiredOpenStatus: boolean;
|
||||
setDesiredOpenStatus?: (isOpen: boolean) => void;
|
||||
isNotControllable?: boolean;
|
||||
}
|
||||
|
||||
export const ResponseSection = ({
|
||||
header,
|
||||
body,
|
||||
status,
|
||||
desiredOpenStatus,
|
||||
setDesiredOpenStatus,
|
||||
isNotControllable,
|
||||
}: ResponseSectionProps) => {
|
||||
const [isOpen, setIsOpen] = useState<boolean | null>(null);
|
||||
|
||||
let icon = null;
|
||||
if (status === "in-progress") {
|
||||
icon = (
|
||||
<div className="m-auto">
|
||||
<Grid
|
||||
height="12"
|
||||
width="12"
|
||||
color="#3b82f6"
|
||||
ariaLabel="grid-loading"
|
||||
radius="12.5"
|
||||
wrapperStyle={{}}
|
||||
wrapperClass=""
|
||||
visible={true}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (status === "failed") {
|
||||
icon = <AlertIcon size={16} className="text-red-500" />;
|
||||
}
|
||||
if (status === "success") {
|
||||
icon = <CheckmarkIcon size={16} className="text-green-600" />;
|
||||
}
|
||||
if (status === "warning") {
|
||||
icon = <TriangleAlertIcon size={16} className="text-yellow-600" />;
|
||||
}
|
||||
|
||||
// use `desiredOpenStatus` if user has not clicked to open/close, otherwise use
|
||||
// `isOpen` state
|
||||
const finalIsOpen = isOpen !== null ? isOpen : desiredOpenStatus;
|
||||
return (
|
||||
<div>
|
||||
<div
|
||||
className={`
|
||||
flex
|
||||
my-1
|
||||
p-1
|
||||
rounded
|
||||
select-none
|
||||
${isNotControllable ? "" : "hover:bg-gray-800 cursor-pointer"}`}
|
||||
onClick={() => {
|
||||
if (!isNotControllable) {
|
||||
if (isOpen === null) {
|
||||
setIsOpen(!desiredOpenStatus);
|
||||
} else {
|
||||
setIsOpen(!isOpen);
|
||||
}
|
||||
}
|
||||
if (setDesiredOpenStatus) {
|
||||
setDesiredOpenStatus(!desiredOpenStatus);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div className="my-auto">{icon}</div>
|
||||
<div className="my-auto text-sm text-gray-200 italic">{header}</div>
|
||||
|
||||
{!isNotControllable && (
|
||||
<div className="ml-auto">
|
||||
{finalIsOpen ? (
|
||||
<ChevronDownIcon size={16} className="text-gray-400" />
|
||||
) : (
|
||||
<ChevronLeftIcon size={16} className="text-gray-400" />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{finalIsOpen && <div className="pb-1 mx-2 text-sm mb-1">{body}</div>}
|
||||
</div>
|
||||
);
|
||||
};
|
@ -1,6 +1,7 @@
|
||||
import { Credential, DocumentBoostStatus } from "@/lib/types";
|
||||
import useSWR, { mutate, useSWRConfig } from "swr";
|
||||
import { fetcher } from "./fetcher";
|
||||
import { useState } from "react";
|
||||
|
||||
const CREDENTIAL_URL = "/api/manage/admin/credential";
|
||||
|
||||
@ -14,8 +15,6 @@ export const usePublicCredentials = () => {
|
||||
};
|
||||
};
|
||||
|
||||
const MOST_REACTED_DOCS_URL = "/api/manage/doc-boosts";
|
||||
|
||||
const buildReactedDocsUrl = (ascending: boolean, limit: number) => {
|
||||
return `/api/manage/admin/doc-boosts?ascending=${ascending}&limit=${limit}`;
|
||||
};
|
||||
@ -32,3 +31,18 @@ export const useMostReactedToDocuments = (
|
||||
refreshDocs: () => mutate(url),
|
||||
};
|
||||
};
|
||||
|
||||
export const useObjectState = <T>(
|
||||
initialValue: T
|
||||
): [T, (update: Partial<T>) => void] => {
|
||||
const [state, setState] = useState<T>(initialValue);
|
||||
const set = (update: Partial<T>) => {
|
||||
setState((prevState) => {
|
||||
return {
|
||||
...prevState,
|
||||
...update,
|
||||
};
|
||||
});
|
||||
};
|
||||
return [state, set];
|
||||
};
|
||||
|
16
web/src/lib/search/aiThoughtUtils.ts
Normal file
16
web/src/lib/search/aiThoughtUtils.ts
Normal file
@ -0,0 +1,16 @@
|
||||
const IS_AI_THOUGHTS_OPEN_LOCAL_STORAGE_KEY = "isAIThoughtsOpen";
|
||||
|
||||
export const getAIThoughtsIsOpenSavedValue = () => {
|
||||
// wrapping in `try / catch` to avoid SSR errors during development
|
||||
try {
|
||||
return (
|
||||
localStorage.getItem(IS_AI_THOUGHTS_OPEN_LOCAL_STORAGE_KEY) === "true"
|
||||
);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
export const setAIThoughtsIsOpenSavedValue = (isOpen: boolean) => {
|
||||
localStorage.setItem(IS_AI_THOUGHTS_OPEN_LOCAL_STORAGE_KEY, String(isOpen));
|
||||
};
|
@ -12,6 +12,10 @@ export const SearchType = {
|
||||
};
|
||||
export type SearchType = (typeof SearchType)[keyof typeof SearchType];
|
||||
|
||||
export interface AnswerPiece {
|
||||
answer_piece: string;
|
||||
}
|
||||
|
||||
export interface Quote {
|
||||
quote: string;
|
||||
document_id: string;
|
||||
@ -69,3 +73,8 @@ export interface SearchRequestOverrides {
|
||||
searchType?: SearchType;
|
||||
offset?: number;
|
||||
}
|
||||
|
||||
export interface ValidQuestionResponse {
|
||||
answerable: boolean | null;
|
||||
reasoning: string | null;
|
||||
}
|
||||
|
62
web/src/lib/search/streamingQuestionValidation.ts
Normal file
62
web/src/lib/search/streamingQuestionValidation.ts
Normal file
@ -0,0 +1,62 @@
|
||||
import { AnswerPiece, ValidQuestionResponse } from "./interfaces";
|
||||
import { processRawChunkString } from "./streamingUtils";
|
||||
|
||||
export interface QuestionValidationArgs {
|
||||
query: string;
|
||||
update: (update: Partial<ValidQuestionResponse>) => void;
|
||||
}
|
||||
|
||||
export const questionValidationStreamed = async <T>({
|
||||
query,
|
||||
update,
|
||||
}: QuestionValidationArgs) => {
|
||||
const response = await fetch("/api/stream-query-validation", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
query,
|
||||
collection: "danswer_index",
|
||||
use_keyword: null,
|
||||
filters: null,
|
||||
offset: null,
|
||||
}),
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
const reader = response.body?.getReader();
|
||||
const decoder = new TextDecoder("utf-8");
|
||||
|
||||
let reasoning = "";
|
||||
let previousPartialChunk: string | null = null;
|
||||
while (true) {
|
||||
const rawChunk = await reader?.read();
|
||||
if (!rawChunk) {
|
||||
throw new Error("Unable to process chunk");
|
||||
}
|
||||
const { done, value } = rawChunk;
|
||||
if (done) {
|
||||
break;
|
||||
}
|
||||
|
||||
const [completedChunks, partialChunk] = processRawChunkString<
|
||||
AnswerPiece | ValidQuestionResponse
|
||||
>(decoder.decode(value, { stream: true }), previousPartialChunk);
|
||||
if (!completedChunks.length && !partialChunk) {
|
||||
break;
|
||||
}
|
||||
previousPartialChunk = partialChunk as string | null;
|
||||
|
||||
completedChunks.forEach((chunk) => {
|
||||
if (Object.hasOwn(chunk, "answer_piece")) {
|
||||
reasoning += (chunk as AnswerPiece).answer_piece;
|
||||
update({
|
||||
reasoning,
|
||||
});
|
||||
}
|
||||
|
||||
if (Object.hasOwn(chunk, "answerable")) {
|
||||
update({ answerable: (chunk as ValidQuestionResponse).answerable });
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
47
web/src/lib/search/streamingUtils.ts
Normal file
47
web/src/lib/search/streamingUtils.ts
Normal file
@ -0,0 +1,47 @@
|
||||
type NonEmptyObject = { [k: string]: any };
|
||||
|
||||
const processSingleChunk = <T extends NonEmptyObject>(
|
||||
chunk: string,
|
||||
currPartialChunk: string | null
|
||||
): [T | null, string | null] => {
|
||||
const completeChunk = (currPartialChunk || "") + chunk;
|
||||
try {
|
||||
// every complete chunk should be valid JSON
|
||||
const chunkJson = JSON.parse(completeChunk);
|
||||
return [chunkJson, null];
|
||||
} catch (err) {
|
||||
// if it's not valid JSON, then it's probably an incomplete chunk
|
||||
return [null, completeChunk];
|
||||
}
|
||||
};
|
||||
|
||||
export const processRawChunkString = <T extends NonEmptyObject>(
|
||||
rawChunkString: string,
|
||||
previousPartialChunk: string | null
|
||||
): [T[], string | null] => {
|
||||
/* This is required because, in practice, we see that nginx does not send over
|
||||
each chunk one at a time even with buffering turned off. Instead,
|
||||
chunks are sometimes in batches or are sometimes incomplete */
|
||||
if (!rawChunkString) {
|
||||
return [[], null];
|
||||
}
|
||||
const chunkSections = rawChunkString
|
||||
.split("\n")
|
||||
.filter((chunk) => chunk.length > 0);
|
||||
let parsedChunkSections: T[] = [];
|
||||
let currPartialChunk = previousPartialChunk;
|
||||
chunkSections.forEach((chunk) => {
|
||||
const [processedChunk, partialChunk] = processSingleChunk<T>(
|
||||
chunk,
|
||||
currPartialChunk
|
||||
);
|
||||
if (processedChunk) {
|
||||
parsedChunkSections.push(processedChunk);
|
||||
currPartialChunk = null;
|
||||
} else {
|
||||
currPartialChunk = partialChunk;
|
||||
}
|
||||
});
|
||||
|
||||
return [parsedChunkSections, currPartialChunk];
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user