diff --git a/web/package-lock.json b/web/package-lock.json index 04902e1e325fe297151fd6cbf0a61d94612ef611..f6ab7916fcbd1ddd1e652c9d02ad821843dc2b34 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -21,8 +21,11 @@ "react-chat-elements": "^12.0.13", "react-i18next": "^14.0.0", "react-infinite-scroll-component": "^6.1.0", + "react-markdown": "^9.0.1", + "react-string-replace": "^1.1.1", "umi": "^4.0.90", "umi-request": "^1.4.0", + "unist-util-visit-parents": "^6.0.1", "uuid": "^9.0.1" }, "devDependencies": { @@ -2667,6 +2670,14 @@ "@babel/types": "^7.20.7" } }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmmirror.com/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "dependencies": { + "@types/ms": "*" + } + }, "node_modules/@types/eslint": { "version": "8.56.1", "resolved": "https://registry.npmmirror.com/@types/eslint/-/eslint-8.56.1.tgz", @@ -2690,8 +2701,15 @@ "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "peer": true + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" + }, + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmmirror.com/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", + "dependencies": { + "@types/estree": "*" + } }, "node_modules/@types/glob": { "version": "7.2.0", @@ -2716,6 +2734,14 @@ "resolved": "https://registry.npmmirror.com/@types/hapi__joi/-/hapi__joi-17.1.9.tgz", "integrity": "sha512-oOMFT8vmCTFncsF1engrs04jatz8/Anwx3De9uxnOK4chgSEgWBvFtpSoJo8u3784JNO+ql5tzRR6phHoRnscQ==" }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "dependencies": { + "@types/unist": "*" + } + }, "node_modules/@types/history": { "version": "5.0.0", "resolved": "https://registry.npmmirror.com/@types/history/-/history-5.0.0.tgz", @@ -2787,6 +2813,14 @@ "integrity": "sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==", "dev": true }, + "node_modules/@types/mdast": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/@types/mdast/-/mdast-4.0.3.tgz", + "integrity": "sha512-LsjtqsyF+d2/yFOYaN22dHZI1Cpwkrj+g06G8+qtUKlhovPW89YhqSnfKtMbkgmEtYpH2gydRNULd6y8mciAFg==", + "dependencies": { + "@types/unist": "*" + } + }, "node_modules/@types/minimatch": { "version": "5.1.2", "resolved": "https://registry.npmmirror.com/@types/minimatch/-/minimatch-5.1.2.tgz", @@ -2799,6 +2833,11 @@ "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", "peer": true }, + "node_modules/@types/ms": { + "version": "0.7.34", + "resolved": "https://registry.npmmirror.com/@types/ms/-/ms-0.7.34.tgz", + "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" + }, "node_modules/@types/node": { "version": "20.10.6", "resolved": "https://registry.npmmirror.com/@types/node/-/node-20.10.6.tgz", @@ -2821,8 +2860,7 @@ "node_modules/@types/prop-types": { "version": "15.7.11", "resolved": "https://registry.npmmirror.com/@types/prop-types/-/prop-types-15.7.11.tgz", - "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==", - "dev": true + "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==" }, "node_modules/@types/q": { "version": "1.5.8", @@ -2834,7 +2872,6 @@ "version": "18.2.46", "resolved": "https://registry.npmmirror.com/@types/react/-/react-18.2.46.tgz", "integrity": "sha512-nNCvVBcZlvX4NU1nRRNV/mFl1nNRuTuslAJglQsq+8ldXe5Xv0Wd2f7WTE3jOxhLH2BFfiZGC6GCp+kHQbgG+w==", - "dev": true, "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -2912,8 +2949,7 @@ "node_modules/@types/scheduler": { "version": "0.16.8", "resolved": "https://registry.npmmirror.com/@types/scheduler/-/scheduler-0.16.8.tgz", - "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==", - "dev": true + "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==" }, "node_modules/@types/semver": { "version": "7.5.6", @@ -2926,6 +2962,11 @@ "integrity": "sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw==", "dev": true }, + "node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, "node_modules/@types/use-sync-external-store": { "version": "0.0.3", "resolved": "https://registry.npmmirror.com/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz", @@ -4364,8 +4405,7 @@ "node_modules/@ungap/structured-clone": { "version": "1.2.0", "resolved": "https://registry.npmmirror.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "peer": true + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" }, "node_modules/@vitejs/plugin-react": { "version": "4.0.0", @@ -5216,6 +5256,11 @@ "@babel/core": "^7.0.0" } }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==" + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz", @@ -5557,6 +5602,11 @@ "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001574.tgz", "integrity": "sha512-BtYEK4r/iHt/txm81KBudCUcTy7t+s9emrIaHqjYurQ10x71zJ5VQ9x1dYPcz/b+pKSp4y/v1xSI67A+LzpNyg==" }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==" + }, "node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz", @@ -5570,6 +5620,26 @@ "node": ">=4" } }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==" + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==" + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==" + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==" + }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-3.5.3.tgz", @@ -5777,6 +5847,11 @@ "node": ">= 0.8" } }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==" + }, "node_modules/commander": { "version": "8.3.0", "resolved": "https://registry.npmmirror.com/commander/-/commander-8.3.0.tgz", @@ -6588,6 +6663,14 @@ "node": ">=0.10.0" } }, + "node_modules/decode-named-character-reference": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz", + "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==", + "dependencies": { + "character-entities": "^2.0.0" + } + }, "node_modules/decode-uri-component": { "version": "0.2.2", "resolved": "https://registry.npmmirror.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz", @@ -6772,6 +6855,14 @@ "node": ">=0.4.0" } }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "engines": { + "node": ">=6" + } + }, "node_modules/des.js": { "version": "1.1.0", "resolved": "https://registry.npmmirror.com/des.js/-/des.js-1.1.0.tgz", @@ -6845,6 +6936,14 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "dependencies": { + "dequal": "^2.0.0" + } + }, "node_modules/diffie-hellman": { "version": "5.0.3", "resolved": "https://registry.npmmirror.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz", @@ -7981,6 +8080,11 @@ "node": ">=4.0" } }, + "node_modules/estree-util-is-identifier-name": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==" + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmmirror.com/esutils/-/esutils-2.0.3.tgz", @@ -8129,6 +8233,11 @@ "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==", "dev": true }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, "node_modules/extend-shallow": { "version": "3.0.2", "resolved": "https://registry.npmmirror.com/extend-shallow/-/extend-shallow-3.0.2.tgz", @@ -9038,6 +9147,36 @@ "node": ">= 0.4" } }, + "node_modules/hast-util-to-jsx-runtime": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.0.tgz", + "integrity": "sha512-H/y0+IWPdsLLS738P8tDnrQ8Z+dj12zQQ6WC11TIM21C8WFVoIxcqWXf2H3hiTVZjF1AWqoimGwrTWecWrnmRQ==", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-object": "^1.0.0", + "unist-util-position": "^5.0.0", + "vfile-message": "^4.0.0" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "dependencies": { + "@types/hast": "^3.0.0" + } + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmmirror.com/he/-/he-1.2.0.tgz", @@ -9203,6 +9342,11 @@ "node": ">=8" } }, + "node_modules/html-url-attributes": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/html-url-attributes/-/html-url-attributes-3.0.0.tgz", + "integrity": "sha512-/sXbVCWayk6GDVg3ctOX6nxaVj7So40FcFAnWlWGNAB1LpYKcV5Cd10APjPjW80O7zYW2MsjBV4zZ7IZO5fVow==" + }, "node_modules/html-webpack-plugin": { "version": "5.5.0", "resolved": "https://registry.npmmirror.com/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz", @@ -9400,6 +9544,11 @@ "resolved": "https://registry.npmmirror.com/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, + "node_modules/inline-style-parser": { + "version": "0.2.2", + "resolved": "https://registry.npmmirror.com/inline-style-parser/-/inline-style-parser-0.2.2.tgz", + "integrity": "sha512-EcKzdTHVe8wFVOGEYXiW9WmJXPjqi1T+234YpJr98RiFYKHV3cdy1+3mkTE+KHTHxFFLH51SfaGOoUdW+v7ViQ==" + }, "node_modules/insert-css": { "version": "2.0.0", "resolved": "https://registry.npmmirror.com/insert-css/-/insert-css-2.0.0.tgz", @@ -9471,6 +9620,20 @@ "node": ">= 0.10" } }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==" + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + } + }, "node_modules/is-arguments": { "version": "1.1.1", "resolved": "https://registry.npmmirror.com/is-arguments/-/is-arguments-1.1.1.tgz", @@ -9596,6 +9759,11 @@ "node": ">= 0.4" } }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==" + }, "node_modules/is-descriptor": { "version": "1.0.3", "resolved": "https://registry.npmmirror.com/is-descriptor/-/is-descriptor-1.0.3.tgz", @@ -9710,6 +9878,11 @@ "node": ">=0.10.0" } }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==" + }, "node_modules/is-inside-container": { "version": "1.0.0", "resolved": "https://registry.npmmirror.com/is-inside-container/-/is-inside-container-1.0.0.tgz", @@ -10779,6 +10952,11 @@ "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==", "dev": true }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==" + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmmirror.com/loose-envify/-/loose-envify-1.4.0.tgz", @@ -10882,6 +11060,119 @@ "safe-buffer": "^5.1.2" } }, + "node_modules/mdast-util-from-markdown": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.0.tgz", + "integrity": "sha512-n7MTOr/z+8NAX/wmhhDji8O3bRvPTV/U0oTCaZJkjhPSKTPhS3xufVhKGF8s1pJ7Ox4QgoIU7KHseh09S+9rTA==", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.0.tgz", + "integrity": "sha512-fGCu8eWdKUKNu5mohVGkhBXCXGnOTLuFqOvGMvdikr+J1w7lDJgxThOKpwRWzzbyXAU2hhSwsmssOY4yTokluw==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + } + }, + "node_modules/mdast-util-mdx-jsx": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.1.0.tgz", + "integrity": "sha512-A8AJHlR7/wPQ3+Jre1+1rq040fX9A4Q1jG8JxmSNp/PLPHg80A6475wxTp3KzHpApFH6yWxFotHrJQA3dXP6/w==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-remove-position": "^5.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + } + }, + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.1.0", + "resolved": "https://registry.npmmirror.com/mdast-util-to-hast/-/mdast-util-to-hast-13.1.0.tgz", + "integrity": "sha512-/e2l/6+OdGp/FB+ctrJ9Avz71AN/GRH3oi/3KAx/kMnoUsD6q0woXlDT8lLEeViVKE7oZxE7RXzvO3T8kF2/sA==", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", + "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + } + }, + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "dependencies": { + "@types/mdast": "^4.0.0" + } + }, "node_modules/mdn-data": { "version": "2.0.14", "resolved": "https://registry.npmmirror.com/mdn-data/-/mdn-data-2.0.14.tgz", @@ -10934,6 +11225,217 @@ "node": ">= 8" } }, + "node_modules/micromark": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/micromark/-/micromark-4.0.0.tgz", + "integrity": "sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==", + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-core-commonmark/-/micromark-core-commonmark-2.0.0.tgz", + "integrity": "sha512-jThOz/pVmAYUtkroV3D5c1osFXAMv9e0ypGDOIZuCeAe91/sD6BoE2Sjzt30yuXtwOYUmySOhMas/PVyh02itA==", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-factory-destination/-/micromark-factory-destination-2.0.0.tgz", + "integrity": "sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-factory-label/-/micromark-factory-label-2.0.0.tgz", + "integrity": "sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-factory-title/-/micromark-factory-title-2.0.0.tgz", + "integrity": "sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.0.tgz", + "integrity": "sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-util-chunked/-/micromark-util-chunked-2.0.0.tgz", + "integrity": "sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-util-classify-character/-/micromark-util-classify-character-2.0.0.tgz", + "integrity": "sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.0.tgz", + "integrity": "sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==", + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.1.tgz", + "integrity": "sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-util-decode-string/-/micromark-util-decode-string-2.0.0.tgz", + "integrity": "sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz", + "integrity": "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==" + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.0.tgz", + "integrity": "sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==" + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.0.tgz", + "integrity": "sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.0.tgz", + "integrity": "sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==", + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz", + "integrity": "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.0.tgz", + "integrity": "sha512-vc93L1t+gpR3p8jxeVdaYlbV2jTYteDje19rNSS/H5dlhxUYll5Fy6vJ2cDwP8RnsXi818yGty1ayP55y3W6fg==", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==" + }, + "node_modules/micromark-util-types": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-util-types/-/micromark-util-types-2.0.0.tgz", + "integrity": "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==" + }, "node_modules/micromatch": { "version": "4.0.5", "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.5.tgz", @@ -11787,6 +12289,26 @@ "safe-buffer": "^5.1.1" } }, + "node_modules/parse-entities": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/parse-entities/-/parse-entities-4.0.1.tgz", + "integrity": "sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + } + }, + "node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.10", + "resolved": "https://registry.npmmirror.com/@types/unist/-/unist-2.0.10.tgz", + "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==" + }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmmirror.com/parse-json/-/parse-json-5.2.0.tgz", @@ -12717,6 +13239,11 @@ "resolved": "https://registry.npmmirror.com/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "node_modules/property-information": { + "version": "6.4.1", + "resolved": "https://registry.npmmirror.com/property-information/-/property-information-6.4.1.tgz", + "integrity": "sha512-OHYtXfu5aI2sS2LWFSN5rgJjrQ4pCy8i1jubJLe2QvMF8JJ++HXTUIVWFLfXJoaOfvYYjk2SN8J2wFUWIGXT4w==" + }, "node_modules/proxy-compare": { "version": "2.5.1", "resolved": "https://registry.npmmirror.com/proxy-compare/-/proxy-compare-2.5.1.tgz", @@ -13860,6 +14387,27 @@ "resolved": "https://registry.npmmirror.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" }, + "node_modules/react-markdown": { + "version": "9.0.1", + "resolved": "https://registry.npmmirror.com/react-markdown/-/react-markdown-9.0.1.tgz", + "integrity": "sha512-186Gw/vF1uRkydbsOIkcGXw7aHq0sZOCRFFjGrr7b9+nVZg4UfA4enXCaxm4fUzecU38sWfrNDitGhshuU7rdg==", + "dependencies": { + "@types/hast": "^3.0.0", + "devlop": "^1.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "html-url-attributes": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "unified": "^11.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "peerDependencies": { + "@types/react": ">=18", + "react": ">=18" + } + }, "node_modules/react-merge-refs": { "version": "1.1.0", "resolved": "https://registry.npmmirror.com/react-merge-refs/-/react-merge-refs-1.1.0.tgz", @@ -13982,6 +14530,14 @@ "prop-types": "^15.5.8" } }, + "node_modules/react-string-replace": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/react-string-replace/-/react-string-replace-1.1.1.tgz", + "integrity": "sha512-26TUbLzLfHQ5jO5N7y3Mx88eeKo0Ml0UjCQuX4BMfOd/JX+enQqlKpL1CZnmjeBRvQE8TR+ds9j1rqx9CxhKHQ==", + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/reactcss": { "version": "1.2.3", "resolved": "https://registry.npmmirror.com/reactcss/-/reactcss-1.2.3.tgz", @@ -14270,6 +14826,29 @@ "node": ">= 0.10" } }, + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmmirror.com/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" + } + }, + "node_modules/remark-rehype": { + "version": "11.1.0", + "resolved": "https://registry.npmmirror.com/remark-rehype/-/remark-rehype-11.1.0.tgz", + "integrity": "sha512-z3tJrAs2kIs1AqIIy6pzHmAHlF1hWQ+OdY4/hv+Wxe35EhyLKcajL33iUEn3ScxtFox9nUvRufR/Zre8Q08H/g==", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + } + }, "node_modules/remove-accents": { "version": "0.4.2", "resolved": "https://registry.npmmirror.com/remove-accents/-/remove-accents-0.4.2.tgz", @@ -15043,6 +15622,11 @@ "deprecated": "See https://github.com/lydell/source-map-url#deprecated", "dev": true }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==" + }, "node_modules/spdx-correct": { "version": "3.2.0", "resolved": "https://registry.npmmirror.com/spdx-correct/-/spdx-correct-3.2.0.tgz", @@ -15369,6 +15953,15 @@ "es-abstract": "^1.22.1" } }, + "node_modules/stringify-entities": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/stringify-entities/-/stringify-entities-4.0.3.tgz", + "integrity": "sha512-BP9nNHMhhfcMbiuQKCqMjhDP5yBCAxsPu4pHFFzJ6Alo9dZgY4VLDPutXqIjpRiMoKdp7Av85Gr73Q5uH9k7+g==", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -15415,6 +16008,14 @@ "integrity": "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==", "peer": true }, + "node_modules/style-to-object": { + "version": "1.0.5", + "resolved": "https://registry.npmmirror.com/style-to-object/-/style-to-object-1.0.5.tgz", + "integrity": "sha512-rDRwHtoDD3UMMrmZ6BzOW0naTjMsVZLIjsGleSKS/0Oz+cgCfAPRspaqJuE8rDzpKha/nEvnM0IF4seEAZUTKQ==", + "dependencies": { + "inline-style-parser": "0.2.2" + } + }, "node_modules/style-utils": { "version": "0.3.8", "resolved": "https://registry.npmmirror.com/style-utils/-/style-utils-0.3.8.tgz", @@ -15983,6 +16584,11 @@ "resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==" + }, "node_modules/trim-newlines": { "version": "3.0.1", "resolved": "https://registry.npmmirror.com/trim-newlines/-/trim-newlines-3.0.1.tgz", @@ -15992,6 +16598,11 @@ "node": ">=8" } }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==" + }, "node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.6.2.tgz", @@ -16718,6 +17329,20 @@ "./packages/isomorphic-unfetch" ] }, + "node_modules/unified": { + "version": "11.0.4", + "resolved": "https://registry.npmmirror.com/unified/-/unified-11.0.4.tgz", + "integrity": "sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ==", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + } + }, "node_modules/union-value": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/union-value/-/union-value-1.0.1.tgz", @@ -16742,6 +17367,58 @@ "node": ">=0.10.0" } }, + "node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "dependencies": { + "@types/unist": "^3.0.0" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "dependencies": { + "@types/unist": "^3.0.0" + } + }, + "node_modules/unist-util-remove-position": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz", + "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-visit": "^5.0.0" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dependencies": { + "@types/unist": "^3.0.0" + } + }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + } + }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmmirror.com/universalify/-/universalify-2.0.1.tgz", @@ -16994,6 +17671,25 @@ "node": ">= 0.8" } }, + "node_modules/vfile": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/vfile/-/vfile-6.0.1.tgz", + "integrity": "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + } + }, + "node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + } + }, "node_modules/vite": { "version": "4.3.1", "resolved": "https://registry.npmmirror.com/vite/-/vite-4.3.1.tgz", @@ -17370,6 +18066,11 @@ "engines": { "node": ">=10" } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmmirror.com/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==" } } } diff --git a/web/package.json b/web/package.json index 9fcffb194c72e850cceb7699edbe996474888a46..43bbdb4374d2949d09ce26082be2140054df011b 100644 --- a/web/package.json +++ b/web/package.json @@ -25,8 +25,11 @@ "react-chat-elements": "^12.0.13", "react-i18next": "^14.0.0", "react-infinite-scroll-component": "^6.1.0", + "react-markdown": "^9.0.1", + "react-string-replace": "^1.1.1", "umi": "^4.0.90", "umi-request": "^1.4.0", + "unist-util-visit-parents": "^6.0.1", "uuid": "^9.0.1" }, "devDependencies": { diff --git a/web/src/assets/svg/assistant.svg b/web/src/assets/svg/assistant.svg new file mode 100644 index 0000000000000000000000000000000000000000..43446a186a4bfdcd1506c05e251c9a86b9d4a6d4 --- /dev/null +++ b/web/src/assets/svg/assistant.svg @@ -0,0 +1,25 @@ +<svg width="42" height="42" viewBox="0 0 42 42" fill="none" xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <path + d="M0 20C0 8.95431 8.95431 0 20 0V0C31.0457 0 40 8.95431 40 20V20C40 31.0457 31.0457 40 20 40V40C8.95431 40 0 31.0457 0 20V20Z" + fill="#DCCCBD" /> + <path + d="M0 20C0 8.95431 8.95431 0 20 0V0C31.0457 0 40 8.95431 40 20V20C40 31.0457 31.0457 40 20 40V40C8.95431 40 0 31.0457 0 20V20Z" + fill="url(#pattern0)" /> + <path + d="M20 39.625C9.16141 39.625 0.375 30.8386 0.375 20C0.375 9.16141 9.16141 0.375 20 0.375C30.8386 0.375 39.625 9.16141 39.625 20C39.625 30.8386 30.8386 39.625 20 39.625Z" + stroke="black" stroke-opacity="0.08" stroke-width="0.75" /> + <path + d="M29.25 35C29.25 38.1756 31.8244 40.75 35 40.75C38.1756 40.75 40.75 38.1756 40.75 35C40.75 31.8244 38.1756 29.25 35 29.25C31.8244 29.25 29.25 31.8244 29.25 35Z" + fill="#17B26A" /> + <path + d="M29.25 35C29.25 38.1756 31.8244 40.75 35 40.75C38.1756 40.75 40.75 38.1756 40.75 35C40.75 31.8244 38.1756 29.25 35 29.25C31.8244 29.25 29.25 31.8244 29.25 35Z" + stroke="white" stroke-width="1.5" /> + <defs> + <pattern id="pattern0" patternContentUnits="objectBoundingBox" width="1" height="1"> + <use xlink:href="#image0_684_15344" transform="translate(-0.157534) scale(0.00273973)" /> + </pattern> + <image id="image0_684_15344" width="480" height="365" + xlink:href="data:image/jpeg;base64,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" /> + </defs> +</svg> \ No newline at end of file diff --git a/web/src/hooks/userSettingHook.ts b/web/src/hooks/userSettingHook.ts new file mode 100644 index 0000000000000000000000000000000000000000..743c790bfb16c47a653c9ba5d843d9cfbcccb13a --- /dev/null +++ b/web/src/hooks/userSettingHook.ts @@ -0,0 +1,22 @@ +import { IUserInfo } from '@/interfaces/database/userSetting'; +import { useCallback, useEffect } from 'react'; +import { useDispatch, useSelector } from 'umi'; + +export const useFetchUserInfo = () => { + const dispatch = useDispatch(); + const fetchUserInfo = useCallback(() => { + dispatch({ type: 'settingModel/getUserInfo' }); + }, [dispatch]); + + useEffect(() => { + fetchUserInfo(); + }, [fetchUserInfo]); +}; + +export const useSelectUserInfo = () => { + const userInfo: IUserInfo = useSelector( + (state: any) => state.settingModel.userInfo, + ); + + return userInfo; +}; diff --git a/web/src/interfaces/database/chat.ts b/web/src/interfaces/database/chat.ts index f7c4a23cbf1b207bbffd04d31f1a053785dbcecc..eb4ec51f370c600471669754315ac0f5db5d8a44 100644 --- a/web/src/interfaces/database/chat.ts +++ b/web/src/interfaces/database/chat.ts @@ -54,7 +54,7 @@ export interface IConversation { dialog_id: string; id: string; message: Message[]; - reference: any[]; + reference: IReference[]; name: string; update_date: string; update_time: number; @@ -64,3 +64,29 @@ export interface Message { content: string; role: MessageType; } + +export interface IReference { + chunks: Chunk[]; + doc_aggs: Docagg[]; + total: number; +} + +interface Docagg { + count: number; + doc_id: string; + doc_name: string; +} + +interface Chunk { + chunk_id: string; + content_ltks: string; + content_with_weight: string; + doc_id: string; + docnm_kwd: string; + img_id: string; + important_kwd: any[]; + kb_id: string; + similarity: number; + term_similarity: number; + vector_similarity: number; +} diff --git a/web/src/interfaces/database/userSetting.ts b/web/src/interfaces/database/userSetting.ts new file mode 100644 index 0000000000000000000000000000000000000000..76a61fee4d60a8a5852218b41eb9b3cae910dfb7 --- /dev/null +++ b/web/src/interfaces/database/userSetting.ts @@ -0,0 +1,21 @@ +export interface IUserInfo { + access_token: string; + avatar?: any; + color_schema: string; + create_date: string; + create_time: number; + email: string; + id: string; + is_active: string; + is_anonymous: string; + is_authenticated: string; + is_superuser: boolean; + language: string; + last_login_time: string; + login_channel: string; + nickname: string; + password: string; + status: string; + update_date: string; + update_time: number; +} diff --git a/web/src/layouts/components/header/index.tsx b/web/src/layouts/components/header/index.tsx index 9d69a44647858dddb7baf3585b97b33c65aa89ea..7705cae780c871e103405c3b6945d812836165f0 100644 --- a/web/src/layouts/components/header/index.tsx +++ b/web/src/layouts/components/header/index.tsx @@ -19,17 +19,20 @@ const RagHeader = () => { const navigate = useNavigate(); const { pathname } = useLocation(); - const tagsData = [ - { path: '/knowledge', name: 'Knowledge Base', icon: KnowledgeBaseIcon }, - { path: '/chat', name: 'Chat', icon: StarIon }, - { path: '/file', name: 'File Management', icon: FileIcon }, - ]; + const tagsData = useMemo( + () => [ + { path: '/knowledge', name: 'Knowledge Base', icon: KnowledgeBaseIcon }, + { path: '/chat', name: 'Chat', icon: StarIon }, + { path: '/file', name: 'File Management', icon: FileIcon }, + ], + [], + ); const currentPath = useMemo(() => { return ( tagsData.find((x) => pathname.startsWith(x.path))?.name || 'knowledge' ); - }, [pathname]); + }, [pathname, tagsData]); const handleChange = (path: string) => { navigate(path); @@ -48,7 +51,7 @@ const RagHeader = () => { > <Space size={12}> <Logo className={styles.appIcon}></Logo> - <label className={styles.appName}>Infinity flow</label> + <label className={styles.appName}>RagFlow</label> </Space> <Space size={[0, 8]} wrap> <Radio.Group diff --git a/web/src/layouts/components/user/index.tsx b/web/src/layouts/components/user/index.tsx index 519e1c69b400b6446273b4ae3ca3b16f4c979a0b..67aff60ea6acfab947370912ddeff977fd41aa5a 100644 --- a/web/src/layouts/components/user/index.tsx +++ b/web/src/layouts/components/user/index.tsx @@ -1,3 +1,4 @@ +import { useFetchUserInfo, useSelectUserInfo } from '@/hooks/userSettingHook'; import authorizationUtil from '@/utils/authorizationUtil'; import type { MenuProps } from 'antd'; import { Avatar, Button, Dropdown } from 'antd'; @@ -7,6 +8,7 @@ import { history } from 'umi'; const App: React.FC = () => { const { t } = useTranslation(); + const userInfo = useSelectUserInfo(); const logout = () => { authorizationUtil.removeAll(); @@ -36,13 +38,18 @@ const App: React.FC = () => { ), }, ]; - }, []); + }, [t]); + + useFetchUserInfo(); return ( <Dropdown menu={{ items }} placement="bottomLeft" arrow> <Avatar size={32} - src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" + src={ + userInfo.avatar ?? + 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png' + } /> </Dropdown> ); diff --git a/web/src/pages/chat/chat-container/index.less b/web/src/pages/chat/chat-container/index.less index ff6eec79c4a353543101b6b604719dd5041402a1..c0ce04b554a41d1706c1191501783f732e9f9bd2 100644 --- a/web/src/pages/chat/chat-container/index.less +++ b/web/src/pages/chat/chat-container/index.less @@ -1,11 +1,34 @@ .chatContainer { padding: 0 24px 24px; + .messageContainer { + overflow-y: auto; + } } .messageItem { - .messageItemContent { + padding: 24px 0; + .messageItemSection { display: inline-block; - width: 300px; + } + .messageItemSectionLeft { + width: 70%; + } + .messageItemSectionRight { + width: 30%; + } + .messageItemContent { + display: inline-flex; + gap: 20px; + } + .messageItemContentReverse { + flex-direction: row-reverse; + } + .messageText { + padding: 0 14px; + background-color: rgba(249, 250, 251, 1); + } + .referenceIcon { + padding: 0 6px; } } diff --git a/web/src/pages/chat/chat-container/index.tsx b/web/src/pages/chat/chat-container/index.tsx index b58b52f65c67bad9b5bde63244d652e2926e27d1..31d939ff506dfc6c4b066bff950d9ba5a8c49e71 100644 --- a/web/src/pages/chat/chat-container/index.tsx +++ b/web/src/pages/chat/chat-container/index.tsx @@ -1,17 +1,59 @@ -import { Button, Flex, Input, Typography } from 'antd'; -import { ChangeEventHandler, useState } from 'react'; - -import { Message } from '@/interfaces/database/chat'; +import { ReactComponent as AssistantIcon } from '@/assets/svg/assistant.svg'; +import { MessageType } from '@/constants/chat'; +import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks'; +import { useSelectUserInfo } from '@/hooks/userSettingHook'; +import { IReference, Message } from '@/interfaces/database/chat'; +import { Avatar, Button, Flex, Input, Popover } from 'antd'; import classNames from 'classnames'; +import { ChangeEventHandler, useCallback, useMemo, useState } from 'react'; +import reactStringReplace from 'react-string-replace'; import { useFetchConversation, useSendMessage } from '../hooks'; - -import { MessageType } from '@/constants/chat'; import { IClientConversation } from '../interface'; + +import { InfoCircleOutlined } from '@ant-design/icons'; +import Markdown from 'react-markdown'; +import { visitParents } from 'unist-util-visit-parents'; import styles from './index.less'; -const { Paragraph } = Typography; +const rehypeWrapReference = () => { + return function wrapTextTransform(tree: any) { + visitParents(tree, 'text', (node, ancestors) => { + if (ancestors.at(-1).tagName !== 'custom-typography') { + node.type = 'element'; + node.tagName = 'custom-typography'; + node.properties = {}; + node.children = [{ type: 'text', value: node.value }]; + } + }); + }; +}; + +const MessageItem = ({ item }: { item: Message; references: IReference[] }) => { + const userInfo = useSelectUserInfo(); + + const popoverContent = useMemo( + () => ( + <div> + <p>Content</p> + <p>Content</p> + </div> + ), + [], + ); + + const renderReference = useCallback( + (text: string) => { + return reactStringReplace(text, /#{2}\d{1,}\${2}/g, (match, i) => { + return ( + <Popover content={popoverContent}> + <InfoCircleOutlined key={i} className={styles.referenceIcon} /> + </Popover> + ); + }); + }, + [popoverContent], + ); -const MessageItem = ({ item }: { item: Message }) => { return ( <div className={classNames(styles.messageItem, { @@ -19,11 +61,50 @@ const MessageItem = ({ item }: { item: Message }) => { [styles.messageItemRight]: item.role === MessageType.User, })} > - <span className={styles.messageItemContent}> - <Paragraph ellipsis={{ tooltip: item.content, rows: 3 }}> - {item.content} - </Paragraph> - </span> + <section + className={classNames(styles.messageItemSection, { + [styles.messageItemSectionLeft]: item.role === MessageType.Assistant, + [styles.messageItemSectionRight]: item.role === MessageType.User, + })} + > + <div + className={classNames(styles.messageItemContent, { + [styles.messageItemContentReverse]: item.role === MessageType.User, + })} + > + {item.role === MessageType.User ? ( + userInfo.avatar ?? ( + <Avatar + size={40} + src={ + userInfo.avatar ?? + 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png' + } + /> + ) + ) : ( + <AssistantIcon></AssistantIcon> + )} + <Flex vertical gap={8} flex={1}> + <b> + {item.role === MessageType.Assistant ? 'Resume Assistant' : 'You'} + </b> + <div className={styles.messageText}> + <Markdown + rehypePlugins={[rehypeWrapReference]} + components={ + { + 'custom-typography': ({ children }: { children: string }) => + renderReference(children), + } as any + } + > + {item.content} + </Markdown> + </div> + </Flex> + </div> + </section> </div> ); }; @@ -32,9 +113,13 @@ const ChatContainer = () => { const [value, setValue] = useState(''); const conversation: IClientConversation = useFetchConversation(); const { sendMessage } = useSendMessage(); + const loading = useOneNamespaceEffectsLoading('chatModel', [ + 'completeConversation', + 'getConversation', + ]); const handlePressEnter = () => { - console.info(value); + setValue(''); sendMessage(value); }; @@ -44,17 +129,23 @@ const ChatContainer = () => { return ( <Flex flex={1} className={styles.chatContainer} vertical> - <Flex flex={1} vertical> - {conversation?.message?.map((message) => ( - <MessageItem key={message.id} item={message}></MessageItem> - ))} + <Flex flex={1} vertical className={styles.messageContainer}> + <div> + {conversation?.message?.map((message) => ( + <MessageItem + key={message.id} + item={message} + references={conversation.reference} + ></MessageItem> + ))} + </div> </Flex> <Input size="large" placeholder="Message Resume Assistant..." value={value} suffix={ - <Button type="primary" onClick={handlePressEnter}> + <Button type="primary" onClick={handlePressEnter} loading={loading}> Send </Button> } diff --git a/web/src/pages/chat/hooks.ts b/web/src/pages/chat/hooks.ts index dd8e04a98c6ee3a5ed603830774ee1245ab00cc1..57ed30d1877c58d0852032a3cf7bcc932fb7f85e 100644 --- a/web/src/pages/chat/hooks.ts +++ b/web/src/pages/chat/hooks.ts @@ -1,8 +1,8 @@ import showDeleteConfirm from '@/components/deleting-confirm'; import { MessageType } from '@/constants/chat'; -import { IDialog } from '@/interfaces/database/chat'; +import { IConversation, IDialog } from '@/interfaces/database/chat'; import omit from 'lodash/omit'; -import { useCallback, useEffect, useMemo } from 'react'; +import { useCallback, useEffect, useMemo, useState } from 'react'; import { useDispatch, useSearchParams, useSelector } from 'umi'; import { v4 as uuid } from 'uuid'; import { ChatSearchParams, EmptyConversationId } from './constants'; @@ -11,6 +11,8 @@ import { IMessage, VariableTableDataType, } from './interface'; +import { ChatModelState } from './model'; +import { isConversationIdNotExist } from './utils'; export const useFetchDialogList = () => { const dispatch = useDispatch(); @@ -137,16 +139,46 @@ export const useRemoveDialog = () => { return { onRemoveDialog }; }; +export const useGetChatSearchParams = () => { + const [currentQueryParameters] = useSearchParams(); + + return { + dialogId: currentQueryParameters.get(ChatSearchParams.DialogId) || '', + conversationId: + currentQueryParameters.get(ChatSearchParams.ConversationId) || '', + }; +}; + +export const useSetCurrentConversation = () => { + const dispatch = useDispatch(); + + const setCurrentConversation = useCallback( + (currentConversation: IClientConversation) => { + dispatch({ + type: 'chatModel/setCurrentConversation', + payload: currentConversation, + }); + }, + [dispatch], + ); + + return setCurrentConversation; +}; + export const useClickDialogCard = () => { const [currentQueryParameters, setSearchParams] = useSearchParams(); const newQueryParameters: URLSearchParams = useMemo(() => { - return new URLSearchParams(currentQueryParameters.toString()); - }, [currentQueryParameters]); + return new URLSearchParams(); + }, []); const handleClickDialog = useCallback( (dialogId: string) => { newQueryParameters.set(ChatSearchParams.DialogId, dialogId); + // newQueryParameters.set( + // ChatSearchParams.ConversationId, + // EmptyConversationId, + // ); setSearchParams(newQueryParameters); }, [newQueryParameters, setSearchParams], @@ -155,16 +187,6 @@ export const useClickDialogCard = () => { return { handleClickDialog }; }; -export const useGetChatSearchParams = () => { - const [currentQueryParameters] = useSearchParams(); - - return { - dialogId: currentQueryParameters.get(ChatSearchParams.DialogId) || '', - conversationId: - currentQueryParameters.get(ChatSearchParams.ConversationId) || '', - }; -}; - export const useSelectFirstDialogOnMount = () => { const dialogList = useFetchDialogList(); const { dialogId } = useGetChatSearchParams(); @@ -182,70 +204,42 @@ export const useSelectFirstDialogOnMount = () => { //#region conversation -export const useFetchConversationList = (dialogId?: string) => { - const dispatch = useDispatch(); - const conversationList: any[] = useSelector( - (state: any) => state.chatModel.conversationList, - ); - - const fetchConversationList = useCallback(() => { - if (dialogId) { - dispatch({ - type: 'chatModel/listConversation', - payload: { dialog_id: dialogId }, - }); - } - }, [dispatch, dialogId]); - - useEffect(() => { - fetchConversationList(); - }, [fetchConversationList]); - - return conversationList; -}; - -export const useClickConversationCard = () => { - const [currentQueryParameters, setSearchParams] = useSearchParams(); - const newQueryParameters: URLSearchParams = new URLSearchParams( - currentQueryParameters.toString(), - ); - - const handleClickConversation = (conversationId: string) => { - newQueryParameters.set(ChatSearchParams.ConversationId, conversationId); - setSearchParams(newQueryParameters); - }; - - return { handleClickConversation }; -}; - export const useCreateTemporaryConversation = () => { const dispatch = useDispatch(); const { dialogId } = useGetChatSearchParams(); const { handleClickConversation } = useClickConversationCard(); let chatModel = useSelector((state: any) => state.chatModel); - let currentConversation: Pick< + + const currentConversation: Pick< IClientConversation, 'id' | 'message' | 'name' | 'dialog_id' > = chatModel.currentConversation; - let conversationList: IClientConversation[] = chatModel.conversationList; - const createTemporaryConversation = (message: string) => { - const messages = [...(currentConversation?.message ?? [])]; + const conversationList: IClientConversation[] = chatModel.conversationList; + const currentDialog: IDialog = chatModel.currentDialog; + + const setCurrentConversation = useSetCurrentConversation(); + + const createTemporaryConversation = useCallback(() => { + const firstConversation = conversationList[0]; + const messages = [...(firstConversation?.message ?? [])]; if (messages.some((x) => x.id === EmptyConversationId)) { return; } - messages.unshift({ + messages.push({ id: EmptyConversationId, - content: message, + content: currentDialog?.prompt_config?.prologue ?? '', role: MessageType.Assistant, }); + let nextCurrentConversation = currentConversation; + // It’s the back-end data. if ('id' in currentConversation) { - currentConversation = { ...currentConversation, message: messages }; + nextCurrentConversation = { ...currentConversation, message: messages }; } else { // client data - currentConversation = { + nextCurrentConversation = { id: EmptyConversationId, name: 'New conversation', dialog_id: dialogId, @@ -255,23 +249,105 @@ export const useCreateTemporaryConversation = () => { const nextConversationList = [...conversationList]; - nextConversationList.push(currentConversation as IClientConversation); + nextConversationList.unshift( + nextCurrentConversation as IClientConversation, + ); - dispatch({ - type: 'chatModel/setCurrentConversation', - payload: currentConversation, - }); + setCurrentConversation(nextCurrentConversation as IClientConversation); dispatch({ type: 'chatModel/setConversationList', payload: nextConversationList, }); handleClickConversation(EmptyConversationId); - }; + }, [ + dispatch, + currentConversation, + dialogId, + setCurrentConversation, + handleClickConversation, + conversationList, + currentDialog, + ]); return { createTemporaryConversation }; }; +export const useFetchConversationList = () => { + const dispatch = useDispatch(); + const conversationList: any[] = useSelector( + (state: any) => state.chatModel.conversationList, + ); + const { dialogId } = useGetChatSearchParams(); + + const fetchConversationList = useCallback(async () => { + if (dialogId) { + dispatch({ + type: 'chatModel/listConversation', + payload: { dialog_id: dialogId }, + }); + } + }, [dispatch, dialogId]); + + useEffect(() => { + fetchConversationList(); + }, [fetchConversationList]); + + return conversationList; +}; + +export const useSelectConversationList = () => { + const [list, setList] = useState<Array<IConversation>>([]); + let chatModel: ChatModelState = useSelector((state: any) => state.chatModel); + const { conversationList, currentDialog } = chatModel; + const { dialogId } = useGetChatSearchParams(); + const prologue = currentDialog?.prompt_config?.prologue ?? ''; + + const addTemporaryConversation = useCallback(() => { + setList(() => { + const nextList = [ + { + id: '', + name: 'New conversation', + dialog_id: dialogId, + message: [ + { + content: prologue, + role: MessageType.Assistant, + }, + ], + } as IConversation, + ...conversationList, + ]; + return nextList; + }); + }, [conversationList, dialogId, prologue]); + + useEffect(() => { + addTemporaryConversation(); + }, [addTemporaryConversation]); + + return { list, addTemporaryConversation }; +}; + +export const useClickConversationCard = () => { + const [currentQueryParameters, setSearchParams] = useSearchParams(); + const newQueryParameters: URLSearchParams = useMemo( + () => new URLSearchParams(currentQueryParameters.toString()), + [currentQueryParameters], + ); + + const handleClickConversation = useCallback( + (conversationId: string) => { + newQueryParameters.set(ChatSearchParams.ConversationId, conversationId); + setSearchParams(newQueryParameters); + }, + [newQueryParameters, setSearchParams], + ); + + return { handleClickConversation }; +}; + export const useSetConversation = () => { const dispatch = useDispatch(); const { dialogId } = useGetChatSearchParams(); @@ -302,17 +378,20 @@ export const useFetchConversation = () => { const conversation = useSelector( (state: any) => state.chatModel.currentConversation, ); + const setCurrentConversation = useSetCurrentConversation(); const fetchConversation = useCallback(() => { - if (conversationId !== EmptyConversationId && conversationId !== '') { - dispatch({ + if (isConversationIdNotExist(conversationId)) { + dispatch<any>({ type: 'chatModel/getConversation', payload: { conversation_id: conversationId, }, }); + } else { + setCurrentConversation({} as IClientConversation); } - }, [dispatch, conversationId]); + }, [dispatch, conversationId, setCurrentConversation]); useEffect(() => { fetchConversation(); @@ -347,7 +426,7 @@ export const useSendMessage = () => { }; const handleSendMessage = async (message: string) => { - if (conversationId !== EmptyConversationId) { + if (conversationId !== '') { sendMessage(message); } else { const data = await setConversation(message); diff --git a/web/src/pages/chat/index.tsx b/web/src/pages/chat/index.tsx index 33b20e44c3be401a083b750e3aceeb6eb914c0c3..4e3124f32aef0b085c63db5c703bc19de7ff4518 100644 --- a/web/src/pages/chat/index.tsx +++ b/web/src/pages/chat/index.tsx @@ -18,11 +18,11 @@ import ChatContainer from './chat-container'; import { useClickConversationCard, useClickDialogCard, - useCreateTemporaryConversation, useFetchConversationList, useFetchDialog, useGetChatSearchParams, useRemoveDialog, + useSelectConversationList, useSelectFirstDialogOnMount, useSetCurrentDialog, } from './hooks'; @@ -38,12 +38,10 @@ const Chat = () => { const { handleClickDialog } = useClickDialogCard(); const { handleClickConversation } = useClickConversationCard(); const { dialogId, conversationId } = useGetChatSearchParams(); - const list = useFetchConversationList(dialogId); - const { createTemporaryConversation } = useCreateTemporaryConversation(); + const { list: conversationList, addTemporaryConversation } = + useSelectConversationList(); - const selectedDialog = useFetchDialog(dialogId, true); - - const prologue = selectedDialog?.prompt_config?.prologue || ''; + useFetchDialog(dialogId, true); const handleAppCardEnter = (id: string) => () => { setActivated(id); @@ -69,8 +67,8 @@ const Chat = () => { }; const handleCreateTemporaryConversation = useCallback(() => { - createTemporaryConversation(prologue); - }, [createTemporaryConversation, prologue]); + addTemporaryConversation(); + }, [addTemporaryConversation]); const items: MenuProps['items'] = [ { @@ -112,6 +110,8 @@ const Chat = () => { return appItems; }; + useFetchConversationList(); + return ( <Flex className={styles.chatWrapper}> <Flex className={styles.chatAppWrapper}> @@ -171,7 +171,7 @@ const Chat = () => { </Flex> <Divider></Divider> <Flex vertical gap={10} className={styles.chatTitleContent}> - {list.map((x) => ( + {conversationList.map((x) => ( <Card key={x.id} hoverable diff --git a/web/src/pages/chat/model.ts b/web/src/pages/chat/model.ts index ff7f4ffb768a3b627e67c257e29c4c070dd9462e..040959ff7c9523aaf0b8c11704727a2a0d9d744b 100644 --- a/web/src/pages/chat/model.ts +++ b/web/src/pages/chat/model.ts @@ -48,10 +48,11 @@ const model: DvaModel<ChatModelState> = { }; }, setCurrentConversation(state, { payload }) { - const messageList = payload?.message.map((x: Message | IMessage) => ({ - ...x, - id: 'id' in x ? x.id : uuid(), - })); + const messageList = + payload?.message?.map((x: Message | IMessage) => ({ + ...x, + id: 'id' in x ? x.id : uuid(), + })) ?? []; return { ...state, currentConversation: { ...payload, message: messageList }, diff --git a/web/src/pages/chat/utils.ts b/web/src/pages/chat/utils.ts index 997dc3755c28fc51c1d6428ee48c7f28f72571e8..cbec9e2c71a1801b64e5b3818765cac49297824b 100644 --- a/web/src/pages/chat/utils.ts +++ b/web/src/pages/chat/utils.ts @@ -1,4 +1,4 @@ -import { variableEnabledFieldMap } from './constants'; +import { EmptyConversationId, variableEnabledFieldMap } from './constants'; export const excludeUnEnabledVariables = (values: any) => { const unEnabledFields: Array<keyof typeof variableEnabledFieldMap> = @@ -10,3 +10,7 @@ export const excludeUnEnabledVariables = (values: any) => { (key) => `llm_setting.${variableEnabledFieldMap[key]}`, ); }; + +export const isConversationIdNotExist = (conversationId: string) => { + return conversationId !== EmptyConversationId && conversationId !== ''; +}; diff --git a/web/src/pages/setting/model.ts b/web/src/pages/setting/model.ts index 643ed5e717e26339b193bed395614b1c2dad3be1..ce46dc86b3c2edf121aa4e0600eea4c2b38e59d0 100644 --- a/web/src/pages/setting/model.ts +++ b/web/src/pages/setting/model.ts @@ -1,7 +1,7 @@ import { ITenantInfo } from '@/interfaces/database/knowledge'; import { IThirdOAIModelCollection as IThirdAiModelCollection } from '@/interfaces/database/llm'; +import { IUserInfo } from '@/interfaces/database/userSetting'; import userService from '@/services/userService'; -import authorizationUtil from '@/utils/authorizationUtil'; import { message } from 'antd'; import { Nullable } from 'typings'; import { DvaModel } from 'umi'; @@ -16,6 +16,7 @@ export interface SettingModelState { llmInfo: IThirdAiModelCollection; myLlm: any[]; factoriesList: any[]; + userInfo: IUserInfo; } const model: DvaModel<SettingModelState> = { @@ -30,6 +31,7 @@ const model: DvaModel<SettingModelState> = { llmInfo: {}, myLlm: [], factoriesList: [], + userInfo: {} as IUserInfo, }, reducers: { updateState(state, { payload }) { @@ -38,10 +40,11 @@ const model: DvaModel<SettingModelState> = { ...payload, }; }, - }, - subscriptions: { - setup({ dispatch, history }) { - history.listen((location) => {}); + setUserInfo(state, { payload }) { + return { + ...state, + userInfo: payload, + }; }, }, effects: { @@ -63,15 +66,17 @@ const model: DvaModel<SettingModelState> = { } }, *getUserInfo({ payload = {} }, { call, put }) { - const { data, response } = yield call(userService.user_info, payload); - const { retcode, data: res, retmsg } = data; - const userInfo = { - avatar: res.avatar, - name: res.nickname, - email: res.email, - }; - authorizationUtil.setUserInfo(userInfo); + const { data } = yield call(userService.user_info, payload); + const { retcode, data: res } = data; + + // const userInfo = { + // avatar: res.avatar, + // name: res.nickname, + // email: res.email, + // }; + // authorizationUtil.setUserInfo(userInfo); if (retcode === 0) { + yield put({ type: 'setUserInfo', payload: res }); // localStorage.setItem('userInfo',res.) } },