diff --git a/agent-arena/client/.gitignore b/agent-arena/client/.gitignore index 967dded1b2..4ab54ec950 100644 --- a/agent-arena/client/.gitignore +++ b/agent-arena/client/.gitignore @@ -23,3 +23,4 @@ yarn-debug.log* yarn-error.log* .DS_Store +.env \ No newline at end of file diff --git a/agent-arena/client/package-lock.json b/agent-arena/client/package-lock.json index 2d05fd2797..3ce9c3ff9c 100644 --- a/agent-arena/client/package-lock.json +++ b/agent-arena/client/package-lock.json @@ -8,22 +8,32 @@ "name": "client", "version": "0.1.0", "dependencies": { + "@codemirror/lang-javascript": "^6.2.2", "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", + "@uiw/codemirror-theme-material": "^4.23.2", + "@uiw/react-codemirror": "^4.23.2", + "@vercel/analytics": "^1.3.1", "ace-builds": "^1.35.2", + "ansi_up": "^6.0.2", "axios": "^1.7.2", "bootstrap": "^5.3.3", "bootstrap-dark": "^1.0.3", "bootswatch": "^5.3.3", + "dompurify": "^3.1.6", "react": "^18.0.0", "react-ace": "^12.0.0", "react-bootstrap": "^2.10.4", "react-dom": "^18.0.0", + "react-icons": "^5.3.0", + "react-markdown": "^9.0.1", "react-router-dom": "^6.0.0", "react-scripts": "5.0.1", "react-select": "^5.8.0", + "react-terminal-ui": "^1.3.0", "react-toastify": "^10.0.5", + "sanitize-html": "^2.13.0", "styled-components": "^6.1.12", "web-vitals": "^2.1.4" } @@ -2085,6 +2095,107 @@ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==" }, + "node_modules/@codemirror/autocomplete": { + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.18.1.tgz", + "integrity": "sha512-iWHdj/B1ethnHRTwZj+C1obmmuCzquH29EbcKr0qIjA9NfDeBDJ7vs+WOHsFeLeflE4o+dHfYndJloMKHUkWUA==", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.17.0", + "@lezer/common": "^1.0.0" + }, + "peerDependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@codemirror/commands": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.6.2.tgz", + "integrity": "sha512-Fq7eWOl1Rcbrfn6jD8FPCj9Auaxdm5nIK5RYOeW7ughnd/rY5AmPg6b+CfsG39ZHdwiwe8lde3q8uR7CF5S0yQ==", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.4.0", + "@codemirror/view": "^6.27.0", + "@lezer/common": "^1.1.0" + } + }, + "node_modules/@codemirror/lang-javascript": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.2.tgz", + "integrity": "sha512-VGQfY+FCc285AhWuwjYxQyUQcYurWlxdKYT4bqwr3Twnd5wP5WSeu52t4tvvuWmljT4EmgEgZCqSieokhtY8hg==", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.6.0", + "@codemirror/lint": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.17.0", + "@lezer/common": "^1.0.0", + "@lezer/javascript": "^1.0.0" + } + }, + "node_modules/@codemirror/language": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.10.3.tgz", + "integrity": "sha512-kDqEU5sCP55Oabl6E7m5N+vZRoc0iWqgDVhEKifcHzPzjqCegcO4amfrYVL9PmPZpl4G0yjkpTpUO/Ui8CzO8A==", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.23.0", + "@lezer/common": "^1.1.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0", + "style-mod": "^4.0.0" + } + }, + "node_modules/@codemirror/lint": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.8.1.tgz", + "integrity": "sha512-IZ0Y7S4/bpaunwggW2jYqwLuHj0QtESf5xcROewY6+lDNwZ/NzvR4t+vpYgg9m7V8UXLPYqG+lu3DF470E5Oxg==", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/search": { + "version": "6.5.6", + "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.6.tgz", + "integrity": "sha512-rpMgcsh7o0GuCDUXKPvww+muLA1pDJaFrpq/CCHtpQJYz8xopu4D1hPcKRoDD0YlF8gZaqTNIRa4VRBWyhyy7Q==", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/state": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.4.1.tgz", + "integrity": "sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A==" + }, + "node_modules/@codemirror/theme-one-dark": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@codemirror/theme-one-dark/-/theme-one-dark-6.1.2.tgz", + "integrity": "sha512-F+sH0X16j/qFLMAfbciKTxVOwkdAS336b7AXTKOZhy8BR3eH/RelsnLgLFINrpST63mmN2OuwUt0W2ndUgYwUA==", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/highlight": "^1.0.0" + } + }, + "node_modules/@codemirror/view": { + "version": "6.33.0", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.33.0.tgz", + "integrity": "sha512-AroaR3BvnjRW8fiZBalAaK+ZzB5usGgI014YKElYZvQdNH5ZIidHlO+cyf/2rWzyBFRkvG6VhiXeAEbC53P2YQ==", + "dependencies": { + "@codemirror/state": "^6.4.0", + "style-mod": "^4.1.0", + "w3c-keyname": "^2.2.4" + } + }, "node_modules/@csstools/normalize.css": { "version": "12.1.1", "resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-12.1.1.tgz", @@ -3482,6 +3593,37 @@ "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==" }, + "node_modules/@lezer/common": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.1.tgz", + "integrity": "sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ==" + }, + "node_modules/@lezer/highlight": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.1.tgz", + "integrity": "sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==", + "dependencies": { + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@lezer/javascript": { + "version": "1.4.18", + "resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.18.tgz", + "integrity": "sha512-Y8BeHOt4LtcxJgXwadtfSeWPrh0XzklcCHnCVT+vOsxqH4gWmunP2ykX+VVOlM/dusyVyiNfG3lv0f10UK+mgA==", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.1.3", + "@lezer/lr": "^1.3.0" + } + }, + "node_modules/@lezer/lr": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.2.tgz", + "integrity": "sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==", + "dependencies": { + "@lezer/common": "^1.0.0" + } + }, "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { "version": "5.1.1-v1", "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", @@ -4196,6 +4338,14 @@ "@types/node": "*" } }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "dependencies": { + "@types/ms": "*" + } + }, "node_modules/@types/eslint": { "version": "8.56.11", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.11.tgz", @@ -4219,6 +4369,14 @@ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" }, + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", + "dependencies": { + "@types/estree": "*" + } + }, "node_modules/@types/express": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", @@ -4249,6 +4407,14 @@ "@types/node": "*" } }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "dependencies": { + "@types/unist": "*" + } + }, "node_modules/@types/html-minifier-terser": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", @@ -4336,11 +4502,24 @@ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "dependencies": { + "@types/unist": "*" + } + }, "node_modules/@types/mime": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==" }, + "node_modules/@types/ms": { + "version": "0.7.34", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", + "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" + }, "node_modules/@types/node": { "version": "22.3.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.3.0.tgz", @@ -4488,6 +4667,11 @@ "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==" }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==" + }, "node_modules/@types/warning": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.3.tgz", @@ -4732,11 +4916,111 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@uiw/codemirror-extensions-basic-setup": { + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/@uiw/codemirror-extensions-basic-setup/-/codemirror-extensions-basic-setup-4.23.2.tgz", + "integrity": "sha512-eacivkj7wzskl2HBYs4rfN0CbYlsSQh5ADtOYWTpc8Txm4ONw8RTi4/rxF6Ks2vdaovizewU5QaHximbxoNTrw==", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/commands": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/lint": "^6.0.0", + "@codemirror/search": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0" + }, + "funding": { + "url": "https://jaywcjlove.github.io/#/sponsor" + }, + "peerDependencies": { + "@codemirror/autocomplete": ">=6.0.0", + "@codemirror/commands": ">=6.0.0", + "@codemirror/language": ">=6.0.0", + "@codemirror/lint": ">=6.0.0", + "@codemirror/search": ">=6.0.0", + "@codemirror/state": ">=6.0.0", + "@codemirror/view": ">=6.0.0" + } + }, + "node_modules/@uiw/codemirror-theme-material": { + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-material/-/codemirror-theme-material-4.23.2.tgz", + "integrity": "sha512-pt8VEX/HnHBGG6BliSdjR9vOlVJ/rr4/YnMZUKbN/rPvCzAbixcRmIg+lpMo8TlDDhgHJtek9YcOKo6VDNMxgg==", + "dependencies": { + "@uiw/codemirror-themes": "4.23.2" + }, + "funding": { + "url": "https://jaywcjlove.github.io/#/sponsor" + } + }, + "node_modules/@uiw/codemirror-themes": { + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/@uiw/codemirror-themes/-/codemirror-themes-4.23.2.tgz", + "integrity": "sha512-g8x+oPqgbzxXSkHhRf7e1AM1mI9/Nl3URReS89pHitRKv8MZNrE+ey+HE8ycfNXRUatrb6zTSRV3M75uoZwNYw==", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0" + }, + "funding": { + "url": "https://jaywcjlove.github.io/#/sponsor" + }, + "peerDependencies": { + "@codemirror/language": ">=6.0.0", + "@codemirror/state": ">=6.0.0", + "@codemirror/view": ">=6.0.0" + } + }, + "node_modules/@uiw/react-codemirror": { + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/@uiw/react-codemirror/-/react-codemirror-4.23.2.tgz", + "integrity": "sha512-MmFL6P5V1Mr81JLkJyWNedfxENKdRhsvyU7Izji9wp337m8dqRAz7rCF5XWarGKx+iQ7q2H5ryl07nLqKLSvtQ==", + "dependencies": { + "@babel/runtime": "^7.18.6", + "@codemirror/commands": "^6.1.0", + "@codemirror/state": "^6.1.1", + "@codemirror/theme-one-dark": "^6.0.0", + "@uiw/codemirror-extensions-basic-setup": "4.23.2", + "codemirror": "^6.0.0" + }, + "funding": { + "url": "https://jaywcjlove.github.io/#/sponsor" + }, + "peerDependencies": { + "@babel/runtime": ">=7.11.0", + "@codemirror/state": ">=6.0.0", + "@codemirror/theme-one-dark": ">=6.0.0", + "@codemirror/view": ">=6.0.0", + "codemirror": ">=6.0.0", + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, "node_modules/@ungap/structured-clone": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" }, + "node_modules/@vercel/analytics": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@vercel/analytics/-/analytics-1.3.1.tgz", + "integrity": "sha512-xhSlYgAuJ6Q4WQGkzYTLmXwhYl39sWjoMA3nHxfkvG+WdBT25c563a7QhwwKivEOZtPJXifYHR1m2ihoisbWyA==", + "dependencies": { + "server-only": "^0.0.1" + }, + "peerDependencies": { + "next": ">= 13", + "react": "^18 || ^19" + }, + "peerDependenciesMeta": { + "next": { + "optional": true + }, + "react": { + "optional": true + } + } + }, "node_modules/@webassemblyjs/ast": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", @@ -5046,6 +5330,14 @@ "ajv": "^6.9.1" } }, + "node_modules/ansi_up": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ansi_up/-/ansi_up-6.0.2.tgz", + "integrity": "sha512-3G3vKvl1ilEp7J1u6BmULpMA0xVoW/f4Ekqhl8RTrJrhEBkonKn5k3bUc5Xt+qDayA6iDX0jyUh3AbZjB/l0tw==", + "engines": { + "node": "*" + } + }, "node_modules/ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -5663,6 +5955,15 @@ "babel-plugin-transform-react-remove-prop-types": "^0.4.24" } }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -6000,6 +6301,15 @@ "node": ">=4" } }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -6023,6 +6333,42 @@ "node": ">=10" } }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/check-types": { "version": "11.2.3", "resolved": "https://registry.npmjs.org/check-types/-/check-types-11.2.3.tgz", @@ -6217,6 +6563,20 @@ "node": ">=4" } }, + "node_modules/codemirror": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.1.tgz", + "integrity": "sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/commands": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/lint": "^6.0.0", + "@codemirror/search": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0" + } + }, "node_modules/collect-v8-coverage": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", @@ -6259,6 +6619,15 @@ "node": ">= 0.8" } }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/commander": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", @@ -6433,6 +6802,11 @@ "node": ">=10" } }, + "node_modules/crelt": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", + "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==" + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -6914,6 +7288,18 @@ "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==" }, + "node_modules/decode-named-character-reference": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz", + "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/dedent": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", @@ -7089,6 +7475,18 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", @@ -7225,6 +7623,11 @@ "url": "https://github.com/fb55/domhandler?sponsor=1" } }, + "node_modules/dompurify": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.6.tgz", + "integrity": "sha512-cTOAhc36AalkjtBpfG6O8JimdTMWNXjiePT2xQH/ppBGi/4uIpmj8eKyIkMJErXWARyINV/sB38yf8JCLF5pbQ==" + }, "node_modules/domutils": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", @@ -8175,6 +8578,15 @@ "node": ">=4.0" } }, + "node_modules/estree-util-is-identifier-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/estree-walker": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", @@ -8308,6 +8720,11 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -9116,6 +9533,44 @@ "node": ">= 0.4" } }, + "node_modules/hast-util-to-jsx-runtime": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -9239,6 +9694,15 @@ "node": ">=12" } }, + "node_modules/html-url-attributes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.0.tgz", + "integrity": "sha512-/sXbVCWayk6GDVg3ctOX6nxaVj7So40FcFAnWlWGNAB1LpYKcV5Cd10APjPjW80O7zYW2MsjBV4zZ7IZO5fVow==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/html-webpack-plugin": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz", @@ -9514,6 +9978,11 @@ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, + "node_modules/inline-style-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.3.tgz", + "integrity": "sha512-qlD8YNDqyTKTyuITrDOffsl6Tdhv+UC4hcdAVuQsK4IMQ99nSgd1MIA/Q+jQYoh9r3hVUXhYh7urSRmXPkW04g==" + }, "node_modules/internal-slot": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", @@ -9543,6 +10012,28 @@ "node": ">= 10" } }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/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" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/is-arguments": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", @@ -9682,6 +10173,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/is-docker": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", @@ -9756,6 +10256,15 @@ "node": ">=0.10.0" } }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/is-map": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", @@ -9832,6 +10341,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-potential-custom-element-name": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", @@ -12330,6 +12847,15 @@ "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -12403,39 +12929,183 @@ "tmpl": "1.0.5" } }, - "node_modules/mdn-data": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", - "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==" - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "engines": { - "node": ">= 0.6" + "node_modules/mdast-util-from-markdown": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.1.tgz", + "integrity": "sha512-aJEUyzZ6TzlsX2s5B4Of7lN7EQtAxvtradMMglCQDyaTFgse6CmtmdJ15ElnVRlCg1vpNyVtbem0PWzlNieZsA==", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/memfs": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", - "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.0.tgz", + "integrity": "sha512-fGCu8eWdKUKNu5mohVGkhBXCXGnOTLuFqOvGMvdikr+J1w7lDJgxThOKpwRWzzbyXAU2hhSwsmssOY4yTokluw==", "dependencies": { - "fs-monkey": "^1.0.4" + "@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" }, - "engines": { - "node": ">= 4.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/memoize-one": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", - "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" + "node_modules/mdast-util-mdx-jsx": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.1.3.tgz", + "integrity": "sha512-bfOjvNt+1AcbPLTFMFWY149nJz0OjmewJs3LQQ5pIyVGxP4CdOqNVJL6kTaM5c68p8q82Xv3nCyFfUnuEcH3UQ==", + "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-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", + "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdn-data": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", + "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "dependencies": { + "fs-monkey": "^1.0.4" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" }, "node_modules/merge-stream": { "version": "2.0.0", @@ -12458,6 +13128,427 @@ "node": ">= 0.6" } }, + "node_modules/micromark": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.0.tgz", + "integrity": "sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "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.1", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.1.tgz", + "integrity": "sha512-CUQyKr1e///ZODyD1U3xit6zXwy1a8q2a1S1HKtIlmgvurrEpaw/Y9y6KSIbF8P59cn/NjzHyO+Q2fAyYLQrAA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "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.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.0.tgz", + "integrity": "sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "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.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.0.tgz", + "integrity": "sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "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.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "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.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.0.tgz", + "integrity": "sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "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.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.0.tgz", + "integrity": "sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "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.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "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.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.0.tgz", + "integrity": "sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.0.tgz", + "integrity": "sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "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.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.0.tgz", + "integrity": "sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "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.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.1.tgz", + "integrity": "sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.0.tgz", + "integrity": "sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "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.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz", + "integrity": "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.0.tgz", + "integrity": "sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.0.tgz", + "integrity": "sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.0.tgz", + "integrity": "sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz", + "integrity": "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "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.1", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.1.tgz", + "integrity": "sha512-jZNtiFl/1aY73yS3UGQkutD0UbhTt68qnRpw2Pifmz5wV9h8gOVsN70v+Lq/f1rKaU/W8pxRe8y8Q9FX1AOe1Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "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.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.0.tgz", + "integrity": "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, "node_modules/micromatch": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", @@ -13020,6 +14111,30 @@ "node": ">=6" } }, + "node_modules/parse-entities": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/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" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==" + }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -13037,6 +14152,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parse-srcset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz", + "integrity": "sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==" + }, "node_modules/parse5": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", @@ -14544,6 +15664,15 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "node_modules/property-information": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", + "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -14880,6 +16009,14 @@ "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==" }, + "node_modules/react-icons": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.3.0.tgz", + "integrity": "sha512-DnUk8aFbTyQPSkCfF8dbX6kQjXA9DktMeJqfjrg6cK9vwQVMxmcA3BfP4QoiztVmEHtwlTgLFsPuH2NskKT6eg==", + "peerDependencies": { + "react": "*" + } + }, "node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", @@ -14890,6 +16027,31 @@ "resolved": "https://registry.npmjs.org/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.npmjs.org/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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=18", + "react": ">=18" + } + }, "node_modules/react-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", @@ -15020,6 +16182,15 @@ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/react-terminal-ui": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/react-terminal-ui/-/react-terminal-ui-1.3.0.tgz", + "integrity": "sha512-UhCDuYmvBFicduM3QxF5EQrI6ACt4coNt6bMgxX9BEr/v8NRFnYlwuPXtN4a5Q5yE8F090zsP9zIKZzZrxglZg==", + "peerDependencies": { + "react": ">16.13.0", + "react-dom": ">16.13.0" + } + }, "node_modules/react-toastify": { "version": "10.0.5", "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-10.0.5.tgz", @@ -15216,6 +16387,37 @@ "node": ">= 0.10" } }, + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-rehype": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/renderkid": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", @@ -15514,6 +16716,88 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "node_modules/sanitize-html": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.13.0.tgz", + "integrity": "sha512-Xff91Z+4Mz5QiNSLdLWwjgBDm5b1RU6xBT0+12rapjiaR7SwfRdjw8f+6Rir2MXKLrDicRFHdb51hGOAxmsUIA==", + "dependencies": { + "deepmerge": "^4.2.2", + "escape-string-regexp": "^4.0.0", + "htmlparser2": "^8.0.0", + "is-plain-object": "^5.0.0", + "parse-srcset": "^1.0.2", + "postcss": "^8.3.11" + } + }, + "node_modules/sanitize-html/node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/sanitize-html/node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/sanitize-html/node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/sanitize-html/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/sanitize-html/node_modules/htmlparser2": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" + } + }, "node_modules/sanitize.css": { "version": "13.0.0", "resolved": "https://registry.npmjs.org/sanitize.css/-/sanitize.css-13.0.0.tgz", @@ -15790,6 +17074,11 @@ "node": ">= 0.8.0" } }, + "node_modules/server-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/server-only/-/server-only-0.0.1.tgz", + "integrity": "sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==" + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -15966,6 +17255,15 @@ "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", "deprecated": "Please use @jridgewell/sourcemap-codec instead" }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/spdy": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", @@ -16292,6 +17590,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/stringify-object": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", @@ -16389,6 +17700,19 @@ "webpack": "^5.0.0" } }, + "node_modules/style-mod": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz", + "integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==" + }, + "node_modules/style-to-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.7.tgz", + "integrity": "sha512-uSjr59G5u6fbxUfKbb8GcqMGT3Xs9v5IbPkjb0S16GyOeBLAzSRK0CixBv5YrYvzO6TDLzIS6QCn78tkqWngPw==", + "dependencies": { + "inline-style-parser": "0.2.3" + } + }, "node_modules/styled-components": { "version": "6.1.12", "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.12.tgz", @@ -17015,6 +18339,24 @@ "node": ">=8" } }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/tryer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", @@ -17199,16 +18541,16 @@ } }, "node_modules/typescript": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", - "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=14.17" + "node": ">=4.2.0" } }, "node_modules/unbox-primitive": { @@ -17285,6 +18627,35 @@ "node": ">=4" } }, + "node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unified/node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/unique-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", @@ -17296,6 +18667,69 @@ "node": ">=8" } }, + "node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", @@ -17451,6 +18885,32 @@ "node": ">= 0.8" } }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", @@ -17460,6 +18920,11 @@ "browser-process-hrtime": "^1.0.0" } }, + "node_modules/w3c-keyname": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", + "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==" + }, "node_modules/w3c-xmlserializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", @@ -18337,6 +19802,15 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } } } } diff --git a/agent-arena/client/package.json b/agent-arena/client/package.json index cc5e2fa7fe..a463393c58 100644 --- a/agent-arena/client/package.json +++ b/agent-arena/client/package.json @@ -3,22 +3,32 @@ "version": "0.1.0", "private": true, "dependencies": { + "@codemirror/lang-javascript": "^6.2.2", "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", + "@uiw/codemirror-theme-material": "^4.23.2", + "@uiw/react-codemirror": "^4.23.2", + "@vercel/analytics": "^1.3.1", "ace-builds": "^1.35.2", + "ansi_up": "^6.0.2", "axios": "^1.7.2", "bootstrap": "^5.3.3", "bootstrap-dark": "^1.0.3", "bootswatch": "^5.3.3", + "dompurify": "^3.1.6", "react": "^18.0.0", "react-ace": "^12.0.0", "react-bootstrap": "^2.10.4", "react-dom": "^18.0.0", + "react-icons": "^5.3.0", + "react-markdown": "^9.0.1", "react-router-dom": "^6.0.0", "react-scripts": "5.0.1", "react-select": "^5.8.0", + "react-terminal-ui": "^1.3.0", "react-toastify": "^10.0.5", + "sanitize-html": "^2.13.0", "styled-components": "^6.1.12", "web-vitals": "^2.1.4" }, diff --git a/agent-arena/client/public/agents_desc.txt b/agent-arena/client/public/agents_desc.txt new file mode 100644 index 0000000000..f9dd0b2cc9 --- /dev/null +++ b/agent-arena/client/public/agents_desc.txt @@ -0,0 +1,429 @@ +<>: + +langchain brave-search agent +langchain google-serper search agent +langchain alpha-vantage stock agent +sql agent plotter langchain +sql agent plotter llamaindex +openai assistant customer support chatbot +langchain Google Jobs +langchain ArXiv Article Fetcher +openai assistant code interpreter +openai assistant function calling +openai general assistant +anthropic pdf upload summarization +anthropic web page reader +anthropic sql query +langchain You.com Search +anthropic calculator tool +anthropic customer service agent +langchain Pandas DataFrame +langchain Wolfram Alpha +langchain NASA Toolkit +langchain Yahoo Finance News +langchain OpenWeatherMap +langchain GraphQL API Integration +crewai AI Crew for Game Building +crewai AI Crew for Trip Planning +crewai Meeting Preparation Agent Crew +langchain Gmail Toolkit +langchain Python REPL +langchain JSON Toolkit +langchain Google Lens +langchain Shell +langchain Wikipedia +langchain PubMed Biomedical Literature Tool +langchain YouTube Search +langchain Golden Query Integration +langchain AskNews +langchain Tavily Search +langchain Eden AI Integration +langchain Exa Search Integration +langchain Dall-E Image Generator +langchain Riza Code Interpreter +llamaindex ArXiv Article Fetcher +llamaindex OpenWeatherMap +llamaindex Exa Search Integration +llamaindex Yahoo Finance News +llamaindex brave-search agent +llamaindex GraphQL API Integration +llamaindex Wolfram Alpha +llamaindex Tavily Research Tool +llamaindex code interpreter +llamaindex wikipedia +llamaindex OpenAPI Tool +llamaindex Yelp Tool + +<>: + +Name: langchain brave-search agent +Description: The langchain brave-search agent is a powerful AI-driven tool designed to harness the capabilities of Brave Search to provide accurate and efficient answers to various queries. It specializes in searching for information across diverse topics, offering insights, summaries, and factual details from a privacy-centric search engine. This agent is particularly effective for users seeking reliable information without compromising their data privacy. +Prompt 1: "What are the benefits of using Brave Search compared to traditional search engines?" +Prompt 2: "Can you find the latest news articles about climate change?" + +----- + +Name: langchain google-serper search agent +Description: The langchain google-serper search agent is a powerful AI tool designed to retrieve and synthesize information from the web using Google search capabilities. This agent excels in answering a wide range of queries by leveraging the vast repository of knowledge available online, effectively providing real-time information, insights, and actionable data tailored to user needs. Whether you require answers to complex questions or quick facts, this agent acts as a bridge between users and the web's resources to deliver accurate and relevant results. +Prompt 1: What are the latest developments in AI technology as of this month? +Prompt 2: Can you find a summary of the most popular articles about climate change published this week? + +----- + +Name: langchain alpha-vantage stock agent +Description: The langchain alpha-vantage stock agent is designed to provide real-time and historical stock market data through integration with the Alpha Vantage API. This agent can retrieve essential information about stock prices, volume, market capitalization, and other financial metrics, making it a valuable tool for investors and analysts alike. Whether you're looking to analyze market trends or track specific stock performances, this agent offers concise and accurate insights into the stock market. +Prompt 1: What was the closing price of MSFT stock last Friday? +Prompt 2: Can you provide the historical data for AAPL stock for the last month? + +----- + +Name: sql agent plotter langchain +Description: The SQL Agent Plotter Langchain is an advanced AI agent designed to assist users in visualizing and interpreting data stored in relational databases. By leveraging SQL queries, this agent enables users to generate insightful plots and charts instantly, making data analysis more accessible and efficient. Whether you are looking to identify trends, display relationships, or summarize datasets, the SQL Agent Plotter Langchain provides tailored visualizations based on your specific queries and requirements. +Prompt 1: "Can you create a bar chart showing the sales revenue by product category for the last quarter?" +Prompt 2: "What does the trend of monthly active users look like over the past year? Please plot it." + +----- + +Name: sql agent plotter llamaindex +Description: The SQL Agent Plotter LlamaIndex is an advanced AI-driven tool designed to help users visualize and analyze data stored in SQL databases. By leveraging the capabilities of LlamaIndex, it enables easy plotting and representation of complex data sets, allowing for insightful analysis and decision-making processes. Whether you're looking to generate trend graphs, pie charts, or bar plots, this agent integrates seamlessly with SQL queries to provide immediate, actionable visualizations that enhance data comprehension. +Prompt 1: Can you create a line graph showing the sales trends over the last 12 months from the sales_data table? +Prompt 2: Please generate a bar chart comparing the number of customers by region from the customer_info table. + +----- + +Name: openai assistant customer support chatbot +Description: The OpenAI Assistant Customer Support Chatbot is designed to provide efficient and reliable assistance to customers by answering queries, troubleshooting issues, and guiding users through product features. With its advanced natural language processing capabilities, the chatbot understands customer concerns and delivers prompt responses to improve their experience, ensuring they receive the information they need without the hassle of waiting. +Prompt 1: Can you help me reset my password for my OpenAI account? +Prompt 2: What are the hours of customer support service for OpenAI products? + +----- + +Name: langchain Google Jobs +Description: langchain Google Jobs is an advanced language model agent designed to help users find job opportunities, analyze employment trends, and navigate the job application process using data from Google Jobs. It leverages a vast database of listings and user-friendly search features to offer tailored job recommendations, career advice, and insights into specific industries, helping users to make informed decisions in their job search. +Prompt 1: What are the top five marketing jobs available in New York City right now? +Prompt 2: Can you explain the typical qualifications and skills required for a data scientist position? + +----- + +Name: langchain ArXiv Article Fetcher +Description: The langchain ArXiv Article Fetcher is an intelligent agent designed to help users quickly find and retrieve academic articles from the ArXiv repository. Leveraging natural language processing, it can search for relevant papers based on specific keywords, authors, or topics, providing users with summaries and links to the full articles. This tool is perfect for researchers, students, and anyone interested in staying up-to-date with the latest in various fields of science and technology. +Prompt 1: Can you find recent articles on quantum computing from the ArXiv? +Prompt 2: What are the latest papers authored by John Doe in the field of machine learning? + +----- + +Name: OpenAI Assistant Code Interpreter +Description: The OpenAI Assistant Code Interpreter is a powerful language model designed to understand and execute code-related queries. It can assist users in executing small code snippets, debugging errors, and providing explanations for complex programming concepts across various languages such as Python, JavaScript, and more. This interactive coding assistant empowers both novice and experienced programmers to enhance their coding skills and troubleshoot issues promptly. +Prompt 1: Can you help me write a Python function that calculates the factorial of a number? +Prompt 2: I'm getting a TypeError in my JavaScript code; can you help me identify the problem? + +----- + +Name: openai assistant function calling +Description: The OpenAI Assistant Function Calling agent is designed to enhance user interactions by seamlessly executing pre-defined functions based on contextual requests. It intelligently interprets user inputs to determine the appropriate function and can perform tasks like fetching data, performing calculations, or managing scheduling. This agent is particularly useful for applications that require dynamic responses to varying user needs while maintaining a user-friendly conversational flow. +Prompt 1: Can you book a meeting for me tomorrow at 3 PM with John? +Prompt 2: What is the weather like tomorrow in New York City? + +----- + +Name: openai general assistant +Description: The OpenAI General Assistant is a versatile language model designed to assist users with a wide range of inquiries, from simple facts and definitions to more complex problem-solving tasks. Whether you need help with writing, learning a new concept, or seeking advice on various topics, this AI is equipped to provide detailed and informative responses tailored to your needs. It's like having a knowledgeable companion at your fingertips, ready to support you in everyday tasks or deep dives into particular subjects. +Prompt 1: Can you explain the concept of blockchain technology in simple terms? +Prompt 2: What are some effective strategies for improving time management skills? + +----- + +Name: anthropic pdf upload summarization +Description: The anthropic pdf upload summarization agent is designed to process and analyze PDF documents efficiently, delivering concise summaries that capture the essential information within the text. This agent employs advanced natural language processing techniques to extract key points, themes, and insights, making it an invaluable tool for students, researchers, and professionals who need to digest large volumes of information quickly. Users can easily upload PDFs and receive clear, structured summaries tailored to their needs. +Prompt 1: Can you summarize the main findings of the research paper uploaded? +Prompt 2: What are the key arguments presented in the PDF document about climate change? + +----- + +Name: anthropic web page reader +Description: The Anthropic Web Page Reader is an advanced language model designed to comprehend and summarize content from web pages. Utilizing natural language processing, it can interpret articles, blogs, and other web-based texts, allowing users to quickly grasp essential information without the need to read lengthy material. Whether users need insights for research, are looking for specific data points, or want an overview of a topic, this AI agent serves as an efficient tool for extracting valuable knowledge from the Internet. +Prompt 1: Can you summarize the main points of the article about climate change on this webpage? +Prompt 2: What are the ten most recent news articles on artificial intelligence I can find on this website? + +----- + +Name: anthropic sql query +Description: The anthropic sql query agent is designed to assist users in crafting, understanding, and executing SQL queries with clarity and precision. It is equipped to tackle a range of SQL-related tasks, from basic data retrieval to complex query building involving multiple joins, aggregations, and subqueries. This agent can help both beginners seeking guidance and experienced users looking for optimization tips for their SQL queries. +Prompt 1: How can I retrieve the top 10 highest-paid employees from the `employees` table? +Prompt 2: What SQL query would I use to count the number of orders for each product category in the `orders` table? + +----- + +Name: langchain You.com Search +Description: langchain You.com Search is a powerful AI agent designed to leverage the You.com search engine to deliver accurate and tailored information from the web. Whether you're seeking the latest news, in-depth articles, or quick facts, this agent effectively synthesizes search results to provide concise and relevant answers, enhancing your online research experience. With its advanced natural language processing capabilities, it can understand and respond to a wide range of queries seamlessly. +Prompt 1: What are the latest trends in artificial intelligence as of this month? +Prompt 2: Can you find articles comparing electric vehicles and traditional cars? + +----- + +Name: anthropic calculator tool +Description: The Anthropic Calculator Tool is a sophisticated AI agent designed to assist users in performing complex mathematical calculations, solving equations, and providing step-by-step explanations for various mathematical concepts. Whether you are a student seeking help with homework, a professional needing quick calculations, or simply curious about mathematical principles, this tool is equipped to deliver accurate results and enhance your understanding of mathematics. +Prompt 1: Can you solve the equation 2x + 5 = 15 and explain the steps? +Prompt 2: What is the derivative of the function f(x) = 3x^2 + 2x - 5? + +----- + +Name: anthropic customer service agent +Description: The anthropic customer service agent is designed to provide assistance and resolve inquiries for customers in a friendly and efficient manner. It utilizes advanced language processing capabilities to understand and respond to a wide range of customer needs, from troubleshooting technical issues to providing information about products and services. This AI agent aims to enhance the customer experience by offering quick, accurate, and personalized responses. +Prompt 1: "How can I reset my password for my account?" +Prompt 2: "What are your return and exchange policies?" + +----- + +Name: langchain Pandas DataFrame +Description: The langchain Pandas DataFrame agent is designed to assist users in performing data manipulation and analysis tasks using the powerful Pandas library in Python. It can help users create, read, and transform data within DataFrames, allowing for easy data processing, statistical analysis, and visualization. Whether you need to filter data, group and summarize information, or perform pivot operations, this agent is here to streamline your data handling processes. +Prompt 1: How can I group a DataFrame by a specific column and calculate the average of another column? +Prompt 2: What is the command to remove duplicate rows from a DataFrame in Pandas? + +----- + +Name: langchain Wolfram Alpha +Description: langchain Wolfram Alpha is an AI agent that leverages the computational intelligence of Wolfram Alpha to provide accurate answers and calculations across a wide range of topics including mathematics, science, engineering, and general knowledge. With its capability to process complex queries and data-driven questions, this agent serves as an excellent resource for users seeking precise information or advanced computations. +Prompt 1: What is the derivative of sin(x) with respect to x? +Prompt 2: Can you calculate the distance between Earth and Mars today? + +----- + +Name: langchain NASA Toolkit +Description: The langchain NASA Toolkit is a specialized LLM agent designed to provide accurate information and insights related to NASA's missions, research, and astronomy. This tool can answer inquiries about historical space missions, current projects, and general space science topics. With its expansive knowledge base, it caters to educators, students, and space enthusiasts by offering detailed explanations, mission updates, and educational resources. +Prompt 1: What are the primary objectives of the Artemis program? +Prompt 2: Can you provide details about the Mars Rover mission and its findings? + +----- + +Name: langchain Yahoo Finance News +Description: The langchain Yahoo Finance News agent specializes in providing real-time stock market information, financial news, and insights into investment trends. Equipped with a vast database of financial data and advanced natural language processing capabilities, this agent can assist users in navigating the complex world of finance by delivering accurate and timely answers to their queries related to stocks, market performance, and economic events. +Prompt 1: What was the price of AAPL stock yesterday? +Prompt 2: Can you provide the latest news on Tesla's market earnings report? + +----- + +Name: langchain OpenWeatherMap +Description: langchain OpenWeatherMap is an advanced LLM agent designed to provide users with real-time weather updates, forecasts, and climate data. Utilizing the OpenWeatherMap API, this agent can answer queries related to current weather conditions in different locations, historical weather patterns, and upcoming forecasts, making it an invaluable resource for planning trips or staying informed about weather-related events. +Prompt 1: What is the current temperature in New York City? +Prompt 2: Can you provide a five-day weather forecast for London? + +----- + +Name: langchain GraphQL API Integration +Description: langchain GraphQL API Integration is a powerful AI agent designed to facilitate interaction with GraphQL APIs, enabling users to efficiently query and manipulate data. This agent understands the nuances of GraphQL syntax and semantics, allowing it to formulate precise queries and mutations based on user input. Whether you're looking to fetch specific datasets or modify records within a GraphQL-compliant backend, this agent streamlines the process and delivers accurate results tailored to your needs. +Prompt 1: "Can you retrieve the details of all users with an age greater than 25 from the GraphQL API?" +Prompt 2: "How can I add a new product with a name, price, and description using a GraphQL mutation?" + +----- + +Name: crewai AI Crew for Game Building +Description: crewai is an innovative AI agent designed to assist game developers in creating engaging and immersive gaming experiences. By providing insights into game design principles, asset recommendations, and testing strategies, crewai streamlines the development process and enhances creativity. Whether you are a seasoned developer or just starting, crewai offers tailored support to help bring your game ideas to fruition. +Prompt 1: What are some tips for creating a compelling narrative in a multiplayer game? +Prompt 2: Can you suggest some tools or platforms for designing game assets and animations? + +----- + +Name: crewai AI Crew for Trip Planning +Description: crewai AI is an innovative AI agent designed to assist users in planning their trips efficiently and effortlessly. By leveraging vast travel-related data, it offers personalized recommendations for destinations, accommodations, activities, and itineraries, ensuring that every travel experience is tailored to individual preferences. Whether you're seeking adventure, relaxation, or cultural experiences, crewai AI is your ultimate travel companion, making trip planning a breeze. +Prompt 1: Can you suggest a 5-day itinerary for a family trip to Italy? +Prompt 2: What are the best local restaurants to try in Paris for traditional French cuisine? + +----- + +Name: crewai Meeting Preparation Agent Crew +Description: The crewai Meeting Preparation Agent Crew is designed to assist users in efficiently organizing and preparing for meetings. This AI agent can summarize agendas, provide relevant background information, suggest discussion points, and ensure all necessary materials are ready for smooth collaboration. Ideal for professionals looking to enhance productivity and ensure that all meeting participants are well-informed, this agent acts as a comprehensive digital assistant for any meeting-related needs. +Prompt 1: Can you summarize the agenda for our upcoming team meeting? +Prompt 2: What background information should I provide to the participants for the project discussion? + +----- + +Name: langchain Gmail Toolkit +Description: The langchain Gmail Toolkit is an AI-powered agent designed to enhance email management by facilitating intuitive interactions with your Gmail account. This agent can help users efficiently organize their inboxes, draft responses, and schedule messages, all while providing insights and suggestions based on email context. Whether you need assistance finding important correspondences or automating your email outreach, the langchain Gmail Toolkit streamlines your email workflow to boost productivity. +Prompt 1: Can you help me find all emails from last week that contain the word "meeting"? +Prompt 2: Draft a response to the email from John Doe regarding the project update, thanking him for his insights and asking for a follow-up meeting. + +----- + +Name: langchain Python REPL +Description: The langchain Python REPL is an interactive AI agent that allows users to execute Python code snippets and obtain immediate feedback. It’s designed to help both beginners and experienced programmers by providing a platform for testing Python code, debugging issues, and exploring programming concepts through real-time execution and interactive learning. Whether you're experimenting with simple calculations or delving into complex algorithms, this agent offers a seamless coding experience. +Prompt 1: Can you show me how to calculate the factorial of a number using a Python function? +Prompt 2: What will be the output of the following code: `print([x**2 for x in range(5)])`? + +----- + +Name: langchain JSON Toolkit +Description: The langchain JSON Toolkit is an advanced LLM agent designed to manipulate, parse, and analyze JSON data structures with ease. It can provide insights into the contents of JSON files, generate new JSON objects based on user specifications, and seamlessly convert JSON data to other formats. This agent is particularly useful for developers, data analysts, and people working with APIs, making it easier to handle JSON in a variety of applications. +Prompt 1: Can you extract the value of 'name' from this JSON: {"user": {"name": "Alice", "age": 30}}? +Prompt 2: How can I convert this JSON object to XML format: {"product": {"id": 1, "name": "Laptop", "price": 999.99}}? + +----- + +Name: langchain Google Lens +Description: langchain Google Lens is an advanced AI agent designed to interpret and extract meaningful information from images. Leveraging powerful image recognition and machine learning techniques, this agent can analyze visual data and provide context, descriptions, and relevant information about the objects, texts, and scenes it identifies. Whether you're curious about a landmark in a photo or need help translating text captured through your camera, langchain Google Lens can offer insightful responses to enhance your understanding of the visual world around you. +Prompt 1: What can you tell me about the building in this photo? +Prompt 2: Please translate the text in this image from Spanish to English. + +----- + +Name: langchain Shell +Description: langchain Shell is a powerful language model agent designed to interact with shell commands and scripting environments. It enables users to execute a variety of shell tasks, from file management to system monitoring, all through natural language inputs. With its ability to understand and interpret shell commands, it streamlines command-line operations for both novice and experienced users, enhancing efficiency and user experience in terminal environments. +Prompt 1: How do I list all files in the current directory? +Prompt 2: Can you show me the command to check the disk usage of my system? + +----- + +Name: langchain Wikipedia +Description: langchain Wikipedia is a powerful AI agent designed to access and summarize information from Wikipedia, providing users with concise and relevant details on a wide range of topics. This agent excels at quickly retrieving factual data, definitions, historical context, and overviews from the vast repository of user-generated knowledge found on the Wikipedia platform, making it an invaluable tool for research, fact-checking, and general inquiry. +Prompt 1: Can you give me a summary of the history of the Roman Empire? +Prompt 2: What are the main contributions of Isaac Newton to science? + +----- + +Name: langchain PubMed Biomedical Literature Tool +Description: The langchain PubMed Biomedical Literature Tool is an advanced AI agent designed to assist researchers, healthcare professionals, and students in navigating and extracting valuable information from the vast repository of biomedical literature available in PubMed. This tool utilizes natural language processing to provide precise answers to inquiries about research articles, drug interactions, clinical guidelines, and trending biomedical topics. It can help streamline the literature review process, making it easier to access relevant studies and extract essential insights from the continuously evolving field of biomedicine. +Prompt 1: Can you summarize the findings of the latest research on CRISPR technology? +Prompt 2: What are the common side effects of the new COVID-19 vaccine according to recent studies? + +----- + +Name: langchain YouTube Search +Description: langchain YouTube Search is a powerful AI agent designed to streamline the process of finding and retrieving content from the vast library of YouTube videos. With advanced natural language processing capabilities, it can understand user queries and deliver accurate results, whether you’re looking for tutorials, music videos, vlogs, or any specific topic of interest. This agent makes it easier for users to discover engaging video content that meets their needs. +Prompt 1: Can you find the latest tutorial on Python programming? +Prompt 2: Show me the most popular music videos from 2023. + +----- + +Name: langchain Golden Query Integration +Description: The langchain Golden Query Integration is an advanced LLM agent designed to streamline access to critical business information and insights by synthesizing vast datasets and providing actionable recommendations. Whether you are looking for market trends, consumer behavior insights, or financial forecasts, this agent harnesses the power of AI to deliver precise and contextually relevant responses to your inquiries, enhancing decision-making processes for businesses and individuals alike. +Prompt 1: What are the latest market trends in the e-commerce sector? +Prompt 2: Can you provide a financial forecast for the renewable energy industry for the next quarter? + +----- + +Name: langchain AskNews +Description: langchain AskNews is a powerful AI agent specifically designed to provide up-to-date news summaries and insights from various media outlets. Utilizing advanced natural language processing capabilities, it can sift through large volumes of information to deliver concise and relevant news articles, trends, and analyses tailored to user interests. Whether you're looking for breaking news, detailed reports, or coverage on specific topics, AskNews makes it easy to stay informed. +Prompt 1: Can you summarize the top news headlines for today? +Prompt 2: What are the latest developments in climate change policy? + +----- + +Name: langchain Tavily Search +Description: langchain Tavily Search is a cutting-edge artificial intelligence agent designed to facilitate intuitive and efficient web searches. Utilizing advanced natural language processing, it allows users to find information quickly across various platforms, offering not just links but also concise summaries of content that are relevant to the user's query. Tavily Search excels in providing relevant search results with context, ensuring users can sift through information easily and effectively. +Prompt 1: Can you find articles about the latest advancements in renewable energy technology? +Prompt 2: What are the top-rated restaurants in Paris according to recent reviews? + +----- + +Name: langchain Eden AI Integration +Description: The langchain Eden AI Integration is a sophisticated language model designed to facilitate seamless interactions with the Eden AI ecosystem. This agent is equipped to provide insightful answers, automate tasks, and enhance decision-making processes across various domains, including natural language processing, machine learning, and data analysis. With its advanced capabilities, it helps users leverage the power of AI to obtain relevant information and optimize workflows, making complex tasks more manageable and efficient. +Prompt 1: How can I create a machine learning model using the Eden AI platform? +Prompt 2: What are the key features of Eden AI's data analysis tools? + +----- + +Name: langchain Exa Search Integration +Description: langchain Exa Search Integration is a powerful AI agent designed to significantly enhance the efficiency and accuracy of information retrieval from vast databases and knowledge sources. Leveraging advanced natural language processing capabilities, it can understand and interpret user queries to deliver precise and relevant results, whether within academic research, corporate data repositories, or general knowledge searches. This integration streamlines the search process, making it easier for users to find exactly what they need. +Prompt 1: Can you summarize the key findings from the latest research paper on renewable energy? +Prompt 2: What are the best practices for data management in cloud computing environments? + +----- + +Name: langchain Dall-E Image Generator +Description: The langchain Dall-E Image Generator is an advanced AI-powered tool designed to create vivid and imaginative images based on textual descriptions. Leveraging the capabilities of OpenAI's DALL-E model, this agent excels at interpreting complex prompts and generating high-quality visual content that aligns with user specifications. From creating fantastical landscapes to unique character designs, it brings creativity to life, making it a valuable resource for artists, marketers, and anyone in need of custom imagery. +Prompt 1: Generate an image of a futuristic cityscape at sunset with flying cars and neon lights. +Prompt 2: Create an illustration of a dragon sitting atop a mountain, surrounded by clouds and a rainbow. + +----- + +Name: langchain Riza Code Interpreter +Description: langchain Riza Code Interpreter is an advanced AI agent designed to assist developers and programmers in understanding and writing code across various programming languages. With its powerful code analysis capabilities, Riza can provide explanations, debug issues, generate code snippets, and even convert code from one language to another. Whether working on a small script or a complex software project, Riza can significantly enhance productivity and learning for both novice and experienced programmers. +Prompt 1: Can you explain how a for loop works in Python and provide a simple example? +Prompt 2: I have this piece of JavaScript code that's returning an error; can you help me debug it? + +----- + +Name: llamaindex ArXiv Article Fetcher +Description: The llamaindex ArXiv Article Fetcher is a powerful AI tool designed to help researchers, students, and enthusiasts easily access and summarize academic articles from the ArXiv repository. Utilizing advanced natural language processing, this agent can retrieve relevant articles based on specified criteria, provide concise summaries, and assist users in navigating through a vast array of research topics efficiently. Whether you need recent publications, specific areas of study, or general insights into complex subjects, this agent streamlines the process of finding and digesting academic literature. +Prompt 1: Can you find and summarize the latest articles on quantum computing from ArXiv? +Prompt 2: What are the key findings in the recent ArXiv paper titled "Deep Learning for Natural Language Processing"? + +----- + +Name: llamaindex OpenWeatherMap +Description: The llamaindex OpenWeatherMap agent is designed to provide real-time weather information and forecasts. It leverages data from OpenWeatherMap to deliver accurate and up-to-date weather conditions for any location worldwide. From temperature readings to precipitation predictions, this agent can assist users in planning their activities based on the latest meteorological data. +Prompt 1: What is the current temperature in New York City? +Prompt 2: Will it rain tomorrow in London? + +----- + +Name: llamaindex Exa Search Integration +Description: The llamaindex Exa Search Integration is a powerful AI agent designed to provide quick and comprehensive search capabilities across a vast array of indexed data. Leveraging advanced natural language processing, it allows users to query large datasets efficiently, offering relevant insights and answers in real-time. This integration supports various file types and databases, making it an invaluable tool for researchers, analysts, and anyone needing immediate access to structured information. +Prompt 1: "What are the key statistics from the last quarterly report of Company XYZ?" +Prompt 2: "Can you summarize the findings from the latest research paper on renewable energy technologies?" + +----- + +Name: llamaindex Yahoo Finance News +Description: The llamaindex Yahoo Finance News agent is designed to provide users with the latest financial news, stock market updates, and insightful analysis sourced from Yahoo Finance. It excels in delivering real-time information, market trends, and highlights from corporate earnings reports. Whether you’re a seasoned investor or a casual market observer, this agent helps you stay informed about the financial landscape and aids in making well-informed investment decisions. +Prompt 1: What are the latest headlines from the stock market today? +Prompt 2: Can you provide an analysis of the recent earnings report for Tesla? + +----- + +Name: llamaindex brave-search agent +Description: The llamaindex brave-search agent is an advanced AI tool designed to efficiently sift through vast amounts of information on the Brave browser. It excels in retrieving relevant data, summarizing articles, and providing insights across various topics. With its unique ability to leverage Brave's privacy-centric search capabilities, this agent ensures that users receive accurate and dependable information while maintaining their privacy. It is especially effective in delivering quick answers to complex queries and aiding users in their online research. +Prompt 1: Can you summarize the latest news on climate change from Brave search results? +Prompt 2: What are the top trending web technologies currently being discussed online? + +----- + +Name: llamaindex GraphQL API Integration +Description: The llamaindex GraphQL API Integration is a powerful LLM agent designed to streamline the process of querying and managing data through GraphQL APIs. It facilitates seamless interactions with various data sources, enabling users to construct efficient queries, retrieve relevant information, and manipulate data directly through intuitive language prompts. This agent is particularly useful for developers, data analysts, and anyone working with GraphQL services who need dynamic and contextual responses based on user-defined queries. +Prompt 1: "Can you retrieve the names and ages of all users from the GraphQL API?" +Prompt 2: "What is the most recent post title and its publication date for the blog section in our GraphQL database?" + +----- + +Name: llamaindex Wolfram Alpha +Description: The llamaindex Wolfram Alpha agent is designed to tap into the computational knowledge engine provided by Wolfram Alpha, allowing users to access a vast range of factual information, calculations, and data analysis. Whether you need to solve mathematical problems, fetch scientific data, or explore historical facts, this agent delivers accurate and insightful responses by interpreting complex queries and providing detailed results from its rich dataset. +Prompt 1: What is the derivative of sin(x)? +Prompt 2: Can you calculate the population growth rate of the United States from 2010 to 2020? + +----- + +Name: llamaindex Tavily Research Tool +Description: The llamaindex Tavily Research Tool is an advanced AI agent designed to facilitate in-depth research and analysis across various domains. It leverages the capabilities of large language models to provide concise explanations, summarize complex topics, and generate insights for users looking to enhance their understanding of specific subjects. Whether you're delving into academic research, industry trends, or emerging technologies, this agent offers a user-friendly interface to access detailed information quickly and efficiently. +Prompt 1: Can you summarize the key findings from the latest climate change report? +Prompt 2: What are the current trends in the artificial intelligence industry? + +----- + +Name: llamaindex code interpreter +Description: The llamaindex code interpreter is an advanced AI agent designed to assist users in understanding and executing programming code. It can analyze code snippets, provide explanations for various programming concepts, and help with debugging or optimizing algorithms. Whether you're a beginner looking to learn programming basics or an experienced developer seeking assistance with complex code, this agent can provide insightful answers and guidance in real-time. +Prompt 1: Can you explain how recursion works in Python with an example? +Prompt 2: I'm getting an error in my JavaScript code. Can you help me debug this line: "console.log('Hello World')"? + +----- + +Name: llamaindex wikipedia +Description: Llamaindex Wikipedia is a powerful AI agent designed to retrieve and summarize information from the vast database of Wikipedia. It excels at providing concise explanations, answering questions related to various topics, and even helping users navigate complex subjects by linking relevant articles. Whether you're looking for information about historical events, scientific concepts, or cultural phenomena, Llamaindex Wikipedia is your go-to companion for swift and reliable knowledge gathering. +Prompt 1: Can you explain the theory of relativity in simple terms? +Prompt 2: What are the main causes and effects of climate change? + +----- + +Name: llamaindex OpenAPI Tool +Description: The llamaindex OpenAPI Tool is a sophisticated language model agent designed to seamlessly interact with various OpenAPI endpoints. It specializes in fetching, processing, and interpreting API responses, allowing users to efficiently access and utilize data from a wide array of web services. This agent excels at providing concise summaries, detailed data analysis, and answering queries by harnessing the capabilities of multiple APIs within one integrated interface. +Prompt 1: Can you retrieve the current weather for New York City using the OpenAPI? +Prompt 2: What are the top trending movies this week according to the movie database API? + +----- + +Name: llamaindex Yelp Tool +Description: The llamaindex Yelp Tool is an AI agent designed to provide detailed insights about local businesses, restaurants, and user experiences based on Yelp data. Whether you're searching for the best places to eat, looking for reviews of a specific venue, or wanting to compare businesses in your area, this agent gathers and synthesizes relevant information to help users make informed decisions. +Prompt 1: "Can you recommend the top-rated Italian restaurants in San Francisco?" +Prompt 2: "What are the most recent reviews for the 'Joe's Coffee Shop' in New York City?" + +----- + diff --git a/agent-arena/client/public/agents_list.txt b/agent-arena/client/public/agents_list.txt new file mode 100644 index 0000000000..1e1ca0a9c5 --- /dev/null +++ b/agent-arena/client/public/agents_list.txt @@ -0,0 +1,53 @@ +langchain brave-search agent +langchain google-serper search agent +langchain alpha-vantage stock agent +sql agent plotter langchain +sql agent plotter llamaindex +openai assistant customer support chatbot +langchain Google Jobs +langchain ArXiv Article Fetcher +openai assistant code interpreter +openai assistant function calling +openai general assistant +anthropic pdf upload summarization +anthropic web page reader +anthropic sql query +langchain You.com Search +anthropic calculator tool +anthropic customer service agent +langchain Pandas DataFrame +langchain Wolfram Alpha +langchain NASA Toolkit +langchain Yahoo Finance News +langchain OpenWeatherMap +langchain GraphQL API Integration +crewai AI Crew for Game Building +crewai AI Crew for Trip Planning +crewai Meeting Preparation Agent Crew +langchain Gmail Toolkit +langchain Python REPL +langchain JSON Toolkit +langchain Google Lens +langchain Shell +langchain Wikipedia +langchain PubMed Biomedical Literature Tool +langchain YouTube Search +langchain Golden Query Integration +langchain AskNews +langchain Tavily Search +langchain Eden AI Integration +langchain Exa Search Integration +langchain Dall-E Image Generator +langchain Riza Code Interpreter +llamaindex ArXiv Article Fetcher +llamaindex OpenWeatherMap +llamaindex Exa Search Integration +llamaindex Yahoo Finance News +llamaindex brave-search agent +llamaindex GraphQL API Integration +llamaindex Wolfram Alpha +llamaindex Tavily Research Tool +llamaindex code interpreter +llamaindex wikipedia +llamaindex OpenAPI Tool +llamaindex Yelp Tool \ No newline at end of file diff --git a/agent-arena/client/public/dark-theme.css b/agent-arena/client/public/dark-theme.css index 30e1918d5a..67fb3d6611 100644 --- a/agent-arena/client/public/dark-theme.css +++ b/agent-arena/client/public/dark-theme.css @@ -77,3 +77,28 @@ select.form-control:focus { color: #ffffff; border: none; } + +.accordion-item { + background-color: #2e2e31; + border: none; +} + +.accordion-button { + background-color: #28293d; + color: #b3b3b3; +} + +.accordion-button:not(.collapsed) { + background-color: #4a90e2; /* Muted blue for active item */ + color: #ffffff; +} + +.accordion-body { + background-color: #34396d; + color: #b3b3b3; + border: none; +} + +.accordion-button:focus { + box-shadow: none; +} \ No newline at end of file diff --git a/agent-arena/client/public/index.html b/agent-arena/client/public/index.html index 63659864f6..e7c9e562c5 100644 --- a/agent-arena/client/public/index.html +++ b/agent-arena/client/public/index.html @@ -7,7 +7,7 @@ diff --git a/agent-arena/client/src/App.js b/agent-arena/client/src/App.js index 9c505db5d7..8b01ad7069 100644 --- a/agent-arena/client/src/App.js +++ b/agent-arena/client/src/App.js @@ -1,5 +1,5 @@ -import React, { useState, useEffect, createContext, useCallback } from 'react'; -import { BrowserRouter as Router, Route, Routes, Link } from 'react-router-dom'; +import React, { useState, useEffect, createContext, useCallback, useContext } from 'react'; +import { BrowserRouter as Router, Route, Routes, Link, useLocation } from 'react-router-dom'; import AgentArena from './components/AgentArena'; import UserProfile from './components/UserProfile'; import SignUp from './components/SignUp'; @@ -7,18 +7,26 @@ import Login from './components/Login'; import UserList from './components/UserList'; import UserPrompts from './components/UserPrompts'; import PromptDetail from './components/PromptDetail'; +import ContactUs from './components/ContactUs'; import Leaderboard from './components/Leaderboard'; +import FAQ from './components/FAQ'; import { Container, Navbar, Nav, Button } from 'react-bootstrap'; +import RequestPasswordReset from './components/RequestPasswordReset'; +import ResetPassword from './components/ResetPassword'; import 'bootstrap/dist/css/bootstrap.min.css'; import { ToastContainer } from 'react-toastify'; +import { FiSun, FiMoon } from 'react-icons/fi'; +import MonitoringDashboard from './components/MonitoringDashboard'; + import 'react-toastify/dist/ReactToastify.css'; import './App.css'; export const ThemeContext = createContext(); const App = () => { + const [isAuthenticated, setIsAuthenticated] = useState(false); - const [theme, setTheme] = useState('dark'); + const [theme, setTheme] = useState('light'); const applyTheme = useCallback((newTheme) => { const linkId = 'dynamic-theme'; @@ -43,7 +51,7 @@ const App = () => { setIsAuthenticated(true); } - const savedTheme = localStorage.getItem('theme') || 'dark'; + const savedTheme = localStorage.getItem('theme') || 'light'; setTheme(savedTheme); applyTheme(savedTheme); }, [applyTheme]); @@ -64,33 +72,11 @@ const App = () => {
- - - LLM Agent Arena - - - - - - + } /> @@ -101,6 +87,11 @@ const App = () => { setIsAuthenticated(true)} />} /> } /> } /> + } /> + } /> + } /> {/* Add the FAQ route */} + } /> {/* Add the Contact Us route */} + } /> @@ -110,4 +101,93 @@ const App = () => { ); }; -export default App; \ No newline at end of file +// NavbarComponent is placed inside Router so useLocation works here +const NavbarComponent = ({ theme, isAuthenticated, handleLogout }) => { + const location = useLocation(); // Now it is inside Router, so useLocation will work + + const handleAgentArenaClick = (e) => { + if (location.pathname === '/') { + e.preventDefault(); + window.location.reload(); + } + }; + + const ThemeToggle = () => { + const { toggleTheme } = useContext(ThemeContext); + + return ( + +
+ {theme === 'dark' ? + : + + } +
+
+ ); + }; + + return ( + + + + Agent Arena + LMSYS Chatbot Arena X Gorilla 🦍 + + + + + + + + + ); +}; + +export default App; diff --git a/agent-arena/client/src/components/AgentArena.js b/agent-arena/client/src/components/AgentArena.js index 1836b63514..09b5d95826 100644 --- a/agent-arena/client/src/components/AgentArena.js +++ b/agent-arena/client/src/components/AgentArena.js @@ -1,58 +1,148 @@ -import React, { useState, useEffect, useContext } from 'react'; -import axios from 'axios'; -import { Container, Row, Col, Button, Form } from 'react-bootstrap'; -import { toast } from 'react-toastify'; -import AgentDropdown from './AgentDropdown'; -import CodeEditor from './CodeEditor'; -import useTypingEffect from './useTypingEffect'; -import { ThemeContext } from '../App'; +import React, { useState, useEffect, useContext } from "react"; +import axios, { all } from "axios"; +import { + Container, + Row, + Col, + Button, + Form, + OverlayTrigger, + Tooltip, + Spinner, +} from "react-bootstrap"; +import { FiPaperclip, FiX } from "react-icons/fi"; // Clipper icon +import { toast } from "react-toastify"; +import { MdClose } from "react-icons/md"; +import AgentDropdown from "./AgentDropdown"; +import CodeEditor from "./CodeEditor"; +import useTypingEffect from "./useTypingEffect"; +import { ThemeContext } from "../App"; +import { Analytics } from "@vercel/analytics/react"; +import { AnsiUp } from "ansi_up"; +import CodeMirror from "@uiw/react-codemirror"; const AgentArena = () => { const [leftAgent, setLeftAgent] = useState(null); const [rightAgent, setRightAgent] = useState(null); const { theme } = useContext(ThemeContext); - - const [goal, setGoal] = useState(''); + const ansiUp = new AnsiUp(); + const [goal, setGoal] = useState(""); const [agents, setAgents] = useState([]); - const [leftExecutedCode, setLeftExecutedCode] = useState(''); - const [rightExecutedCode, setRightExecutedCode] = useState(''); - const [leftOutput, setLeftOutput] = useState(''); - const [rightOutput, setRightOutput] = useState(''); + const [leftExecutedCode, setLeftExecutedCode] = useState(""); + const [rightExecutedCode, setRightExecutedCode] = useState(""); + const [leftOutput, setLeftOutput] = useState([]); + const [rightOutput, setRightOutput] = useState([]); + const [leftCompleted, setLeftCompleted] = useState(false); const [rightCompleted, setRightCompleted] = useState(false); const [ratingEnabled, setRatingEnabled] = useState(false); const [hasVoted, setHasVoted] = useState(false); const [isLoggedIn, setIsLoggedIn] = useState(false); - const [votedResult, setVotedResult] = useState(''); - const [shareURL, setShareURL] = useState(''); + const [votedResult, setVotedResult] = useState(""); + const [shareURL, setShareURL] = useState(""); const [promptId, setPromptId] = useState(null); const [leftFile, setLeftFile] = useState(null); const [rightFile, setRightFile] = useState(null); const [isExample3, setIsExample3] = useState(false); + const [userApiKeys, setUserApiKeys] = useState({}); + const [isRunningBoth, setIsRunningBoth] = useState(false); + const [leftCodeCollapsed, setLeftCodeCollapsed] = useState(false); + const [rightCodeCollapsed, setRightCodeCollapsed] = useState(false); + const [runBothTriggered, setRunBothTriggered] = useState(false); + const [file, setFile] = useState(null); // To store the uploaded file + const [fileUploadAllowed, setFileUploadAllowed] = useState(false); + const [agentDescriptions, setAgentDescriptions] = useState(""); + + const [showLeftRawOutput, setShowLeftRawOutput] = useState(false); + const [showRightRawOutput, setShowRightRawOutput] = useState(false); + + const [leftEventSource, setLeftEventSource] = useState(null); + const [rightEventSource, setRightEventSource] = useState(null); + + const [showAgentNames, setShowAgentNames] = useState(false); + + + const AgentHeader = ({ title }) => ( +

+ {title} +

+ ); const examplePrompts = [ - "Search the web", - "Look up stocks", - "Read MongoDB database and generate plots", - "Understand company expense reports" + "what was AAPL stock yesterday", + "Summarize for me a fascinating article about cats", + "Find cheap hotels in Austin, Texas", + "What is this paper about: 1706.03762", ]; + useEffect(() => { + // Fetch the text file from the public folder + fetch("/agents_desc.txt") + .then((response) => response.text()) + .then((data) => { + setAgentDescriptions(data); // Store the file content in state + }) + .catch((error) => { + console.error("Error fetching the file:", error); + }); + }, []); + const displayedPrompt = useTypingEffect(examplePrompts); + const removeFile = () => { + setFile(null); // Reset file + }; + useEffect(() => { - axios.get('https://agent-arena.vercel.app/api/agents') - .then(response => setAgents(response.data)) - .catch(error => console.error(error)); + axios + .get("https://agent-arena.vercel.app/api/agents") + .then((response) => { + const fetchedAgents = response.data; + if (!fetchedAgents || fetchedAgents.length === 0) { + // Show toast notification that no agents are available and reloading + toast.info("Loading agents, please wait..."); + + // Reload the page after a short delay (e.g., 2 seconds) + setTimeout(() => { + window.location.reload(); + }, 2000); + } else { + setAgents(fetchedAgents); // Set agents if data is available + } + }) + .catch((error) => { + // Show toast notification for error and reload + toast.info("Loading agents, please wait..."); + // Reload the page after a short delay (e.g., 2 seconds) + setTimeout(() => { + window.location.reload(); + }, 2000); + + console.error("Error fetching agents:", error); + }); + - const token = localStorage.getItem('token'); + const token = localStorage.getItem("token"); if (token) { - axios.get('https://agent-arena.vercel.app/api/profile', { - headers: { Authorization: `Bearer ${token}` } - }).then(response => { - setIsLoggedIn(true); - }).catch(error => { - console.error(error); - }); + axios + .get("https://agent-arena.vercel.app/api/profile", { + headers: { Authorization: `Bearer ${token}` }, + }) + .then((response) => { + setIsLoggedIn(true); + setUserApiKeys(response.data.apiKeys || {}); + }) + .catch((error) => { + console.error("Error fetching profile:", error); + }); } }, []); @@ -63,15 +153,97 @@ const AgentArena = () => { }, [leftCompleted, rightCompleted]); const handleLeftSelect = (agent) => { + if (leftEventSource) { + leftEventSource.close(); + setLeftEventSource(null); + } setLeftAgent(agent); - setLeftExecutedCode(goal ? agent.code.replace('Enter Goal/Prompt Here', goal) : agent.code); + setLeftExecutedCode( + goal ? agent.code.replace("Enter Goal/Prompt Here", goal) : agent.code + ); resetVotingState(); + setLeftCodeCollapsed(false); // Ensure code editor is expanded when selecting a new agent + setRightCodeCollapsed(false); // Ensure code editor is expanded when selecting a new agent + if(isExample3){ + setFile(null); + setLeftFile(null); + } + setFileUploadAllowed(agent.allowsFileUpload); + }; + + useEffect(() => { + console.log("Left file updated:", leftFile); + }, [leftFile]); + + useEffect(() => { + console.log("Right file updated:", rightFile); + }, [rightFile]); + + const checkBothCompleted = () => { + if (leftCompleted && rightCompleted) { + setIsRunningBoth(false); + setRatingEnabled(true); + setRunBothTriggered(false); + } + }; + + const buttonStyles = { + search: { + normal: "#c5cae9", + hover: "#9fa8da", + }, + finance: { + normal: "#a2d5f2", + hover: "#8bc3de", + }, + data: { + normal: "#dcedc1", + hover: "#c6d7a8", + }, + research: { + normal: "#ffe0b2", // Research Example button color + hover: "#ffcc80", // Slightly darker shade for hover effect + }, + automation: { normal: "#ffccbc", hover: "#ffab91" }, + }; + + const runBothButtonStyle = { + backgroundColor: theme === "dark" ? "#6f42c1" : "#28a745", // Purple for dark mode, Green for light mode + borderColor: theme === "dark" ? "#6f42c1" : "#28a745", + color: "#fff", + fontSize: "1.25rem", // Make the text larger + fontWeight: "bold", + padding: "10px 25px", + borderRadius: "8px", + boxShadow: "0px 4px 15px rgba(0, 0, 0, 0.2)", // Add shadow for depth + transition: "all 0.3s ease", + }; + + const runBothButtonHoverStyle = { + backgroundColor: "#218838", // Darker green on hover + borderColor: "#218838", }; const handleRightSelect = (agent) => { + if (rightEventSource) { + rightEventSource.close(); + setRightEventSource(null); + } + setRightAgent(agent); - setRightExecutedCode(goal ? agent.code.replace('Enter Goal/Prompt Here', goal) : agent.code); + setRightExecutedCode( + goal ? agent.code.replace("Enter Goal/Prompt Here", goal) : agent.code + ); + // If the selected agent is not part of Example 3, reset the file + setIsExample3(false); + if (isExample3) { + setFile(null); + setRightFile(null); + } resetVotingState(); + setRightCodeCollapsed(false); // Ensure code editor is expanded when selecting a new agent + setLeftCodeCollapsed(false); // Ensure code editor is expanded when selecting a new agent + setFileUploadAllowed(agent.allowsFileUpload); }; const resetVotingState = () => { @@ -79,121 +251,541 @@ const AgentArena = () => { setRightCompleted(false); setRatingEnabled(false); setHasVoted(false); - setLeftOutput(''); - setRightOutput(''); - setVotedResult(''); - setShareURL(''); + setLeftOutput(""); + setRightOutput(""); + setVotedResult(""); + setShareURL(""); setPromptId(null); setLeftFile(null); setRightFile(null); setIsExample3(false); + setIsRunningBoth(false); + setRunBothTriggered(false); + + if (leftEventSource) { + leftEventSource.close(); + setLeftEventSource(null); + } + if (rightEventSource) { + rightEventSource.close(); + setRightEventSource(null); + } }; const handleRating = (rating) => { + toast.success("Your rating has been submitted!"); + setHasVoted(true); setVotedResult(rating); - axios.post('https://agent-arena.vercel.app/api/ratings', { - leftAgent: leftAgent._id, - rightAgent: rightAgent._id, - rating, - executedCode: leftExecutedCode + '\n' + rightExecutedCode, - leftOutput, - rightOutput, - savePrompt: isLoggedIn - }).then(response => { - toast.success(response.data.message); - setHasVoted(true); - setRatingEnabled(false); - setPromptId(response.data.promptId); - }).catch(error => { - toast.error('Error saving rating'); - }); + + setRatingEnabled(false); + + const leftOutputString = leftOutput.join(""); // Convert array to string + const rightOutputString = rightOutput.join(""); // Convert array to string + + + axios + .post("https://agent-arena.vercel.app/api/ratings", { + leftAgent: leftAgent._id, + rightAgent: rightAgent._id, + rating, + executedCode: leftExecutedCode + "\n" + rightExecutedCode, + leftOutput:leftOutputString, + rightOutput:rightOutputString, + savePrompt: isLoggedIn, + }) + .then((response) => { + setPromptId(response.data.promptId); + }) + .catch((error) => { + console.error("Error saving rating:", error); + }); }; const handleSavePrompt = async () => { if (!isLoggedIn) { - toast.error('You need to be logged in to save prompts'); + toast.error("You need to be logged in to save prompts"); return; } + const leftOutputString = leftOutput.join(""); // Convert array to string + const rightOutputString = rightOutput.join(""); // Convert array to string try { - const response = await axios.post('https://agent-arena.vercel.app/api/prompts/save', { - text: goal, - leftAgent: leftAgent._id, - rightAgent: rightAgent._id, - leftExecutedCode, - rightExecutedCode, - votedResult, - leftOutput, - rightOutput - }, { - headers: { Authorization: `Bearer ${localStorage.getItem('token')}` } - }); - toast.success('Prompt saved successfully'); - setPromptId(response.data._id); - setShareURL(`https://www.agent-arena.com/prompts/${response.data._id}`); + const response = await axios.post( + "https://agent-arena.vercel.app/api/prompts/save", + { + text: goal, + leftAgent: leftAgent._id, + rightAgent: rightAgent._id, + leftExecutedCode, + rightExecutedCode, + votedResult, + leftOutput:leftOutputString, + rightOutput:rightOutputString, + }, + { + headers: { Authorization: `Bearer ${localStorage.getItem("token")}` }, + } + ); + toast.success("Prompt saved successfully"); + setPromptId(response.data.promptId); + setShareURL(`https://agent-arena.com/prompts/${response.data.promptId}`); } catch (error) { - console.error('Error saving prompt:', error); - toast.error('Error saving prompt'); + toast.error("Error saving prompt"); } }; - const handleSearch = async () => { + const handleSearch = async (searchGoal) => { if (!agents.length) { - toast.error('No agents available for selection'); + toast.error("No agents available for selection"); return; } + searchGoal = searchGoal.replace(/"/g, ''); + searchGoal = searchGoal.replace(/'/g, ''); + + try { - const agentNames = agents.map(agent => agent.name); - const response = await axios.post('https://agent-arena.vercel.app/api/goals/interpret-goal', { goal, agentNames }); + const agentNames = agents.map((agent) => agent.name); + const response = await axios.post( + "https://agent-arena.vercel.app/api/goals/interpret-goal", + { goal: searchGoal, agentNames, fileUploaded: file } + ); const { agent1, agent2 } = response.data; + setFileUploadAllowed(agent1.allowsFileUpload || agent2.allowsFileUpload); + console.log(fileUploadAllowed); + setLeftAgent(agent1); setRightAgent(agent2); - setLeftExecutedCode(goal ? agent1.code.replace('Enter Goal/Prompt Here', goal) : agent1.code); - setRightExecutedCode(goal ? agent2.code.replace('Enter Goal/Prompt Here', goal) : agent2.code); + setLeftExecutedCode( + searchGoal + ? agent1.code.replace("Enter Goal/Prompt Here", goal) + : agent1.code + ); + setRightExecutedCode( + searchGoal + ? agent2.code.replace("Enter Goal/Prompt Here", goal) + : agent2.code + ); + + if (agent1.allowsFileUpload && file) { + setLeftFile(file); // Set the leftFile to the global file if leftAgent allows file uploads + } + if (agent2.allowsFileUpload && file) { + setRightFile(file); + } resetVotingState(); } catch (error) { - toast.error('Error interpreting goal'); + console.error("Error during agent search:", error); + + // Automatically select fallback agents if no agents are found + const fallbackAgent1 = agents.find( + (agent) => agent.name === "openai general assistant (gpt-4o-2024-08-06)" + ); + const fallbackAgent2 = agents.find( + (agent) => + agent.name === "llamaindex brave-search agent (gpt-4o-2024-08-06)" + ); + + if (fallbackAgent1 && fallbackAgent2) { + setLeftAgent(fallbackAgent1); + setRightAgent(fallbackAgent2); + setLeftExecutedCode( + goal + ? fallbackAgent1.code.replace("Enter Goal/Prompt Here", goal) + : fallbackAgent1.code + ); + setRightExecutedCode( + goal + ? fallbackAgent2.code.replace("Enter Goal/Prompt Here", goal) + : fallbackAgent2.code + ); + resetVotingState(); + // toast.info('Fallback agents selected: openai general assistant and llamaindex brave-search agent.'); + } else { + toast.error( + "There was an issue selecting fallback agents. Please try again." + ); + } + } + }; + + const handleRunBoth = async () => { + setLeftCodeCollapsed(true); + setRightCodeCollapsed(true); + if (!leftAgent || !rightAgent) { + toast.error("Please select both agents before running"); + return; + } + + + if((fileUploadAllowed || leftAgent.allowsFileUpload || rightAgent.allowsFileUpload) && !file) { + toast.error("Please upload a file before running these agents"); + return; + } + + + setIsRunningBoth(true); + setLeftCompleted(false); + setRightCompleted(false); + setRatingEnabled(false); + setHasVoted(false); + setLeftOutput(""); + setRightOutput(""); + setRunBothTriggered((prev) => !prev); + + const leftFormData = new FormData(); + const rightFormData = new FormData(); + + + + + if (fileUploadAllowed && file) { + leftFormData.append("general_file", file); + rightFormData.append("general_file", file); + } + + + leftFormData.append("code", leftExecutedCode); + leftFormData.append("agentId", leftAgent._id); + if (leftFile) { + leftFormData.append("general_file", leftFile); + } + if (file) { + leftFormData.append("general_file", file); + rightFormData.append("general_file", file); + } + Object.keys(userApiKeys).forEach((key) => { + leftFormData.append(key, userApiKeys[key]); + }); + + rightFormData.append("code", rightExecutedCode); + rightFormData.append("agentId", rightAgent._id); + if (rightFile) { + rightFormData.append("general_file", rightFile); + } + Object.keys(userApiKeys).forEach((key) => { + rightFormData.append(key, userApiKeys[key]); + }); + + try { + const [leftResponse, rightResponse] = await Promise.all([ + axios.post("https://agent-arena-location.onrender.com/api/jobs/create", leftFormData, { + headers: { "Content-Type": "multipart/form-data" }, + }), + axios.post("https://agent-arena-location.onrender.com/api/jobs/create", rightFormData, { + headers: { "Content-Type": "multipart/form-data" }, + }), + ]); + + const leftES = streamJobOutput(leftResponse.data.jobId, setLeftOutput, () => { + const blocks = processFullOutput(leftOutput); + setLeftCompleted(true); + checkBothCompleted(); + }); + setLeftEventSource(leftES); // Store the EventSource + + const rightES = streamJobOutput(rightResponse.data.jobId, setRightOutput, () => { + const blocks = processFullOutput(rightOutput); + setRightCompleted(true); + checkBothCompleted(); + }); + setRightEventSource(rightES); // Store the EventSource + } catch (error) { + toast.error("An error occurred while running the agents"); + setIsRunningBoth(false); } }; + const streamJobOutput = (jobId, setOutput, onComplete) => { + const eventSource = new EventSource( + `https://agent-arena-location.onrender.com/api/jobs/${jobId}/stream` + ); + let fullOutput = []; + + // Set a timeout to close the EventSource after 90 seconds + const timeoutId = setTimeout(() => { + eventSource.close(); + onComplete(fullOutput); + toast.info("Execution time exceeded 90 seconds. Output has been truncated."); + }, 90000); // 90 seconds in milliseconds + + eventSource.onmessage = (event) => { + let processedOutput = event.data; + const coloredHtml = ansiUp.ansi_to_html(processedOutput); + fullOutput.push(coloredHtml); + setOutput((prevOutput) => [...prevOutput, coloredHtml]); + }; + + eventSource.onerror = (error) => { + console.error("EventSource failed:", error); + clearTimeout(timeoutId); // Clear the timeout + eventSource.close(); + onComplete(fullOutput); + }; + + eventSource.addEventListener("end", () => { + clearTimeout(timeoutId); // Clear the timeout + eventSource.close(); + onComplete(fullOutput); + }); + + return eventSource; // Return the EventSource instance + }; + + + const handleShareSession = async () => { + + const leftOutputString = leftOutput.join(""); // Convert array to string + const rightOutputString = rightOutput.join(""); // Convert array to string + if (promptId) { + navigator.clipboard.writeText(shareURL); + toast.success("Session link copied to clipboard"); + } else { + try { + const response = await axios.post( + "https://agent-arena.vercel.app/api/prompts/saveWithoutUser", + { + text: goal, + leftAgent: leftAgent._id, + rightAgent: rightAgent._id, + leftExecutedCode, + rightExecutedCode, + votedResult, + leftOutput:leftOutputString, + rightOutput:rightOutputString, + } + ); + const newPromptId = response.data.promptId; + setPromptId(newPromptId); + const newShareURL = `https://www.agent-arena.com/prompts/${newPromptId}`; + setShareURL(newShareURL); + navigator.clipboard.writeText(newShareURL); + toast.success("Session link copied to clipboard"); + } catch (error) { + toast.error("Error sharing session"); + } + } + }; + + const processFullOutput = (fullOutput) => { + console.log(fullOutput); + + // Define keywords + const thoughtKeywords = [ + "thought:", + "Thought:", + "Observation:", + "observation:", + ]; + const actionKeywords = [ + "Action:", + "action:", + "Action input:", + "action input:", + "Action Input:", + "action Input:", + ]; + const answerKeywords = [ + "Final Answer:", + "final answer:", + "Final answer:", + "final Answer:", + "Answer:", + "answer:", + "Output:", + "output:", + ]; + + // Initialize sets + const thoughts = new Set(); + const actions = new Set(); + const answers = new Set(); + + // Ensure that fullOutput is a string + let outputString = String(fullOutput); + + // Remove the span tags and take what is inside the spans only (so basically remove the tags only) + outputString = outputString.replace(//g, ""); + outputString = outputString.replace(/<\/span>/g, ""); + + console.log(outputString); + try { - const response = await axios.post('https://agent-arena.vercel.app/api/share', { - promptId: promptId + // Find matches for each keyword category + thoughtKeywords.forEach((keyword) => { + const matches = outputString.match(new RegExp(`${keyword}.*`, "gi")); + if (matches) thoughts.add(...matches); }); - navigator.clipboard.writeText(response.data.url); - toast.success('Session link copied to clipboard'); - } catch (error) { - toast.error('Error sharing session'); + + actionKeywords.forEach((keyword) => { + const matches = outputString.match(new RegExp(`${keyword}.*`, "gi")); + if (matches) actions.add(...matches); + }); + + answerKeywords.forEach((keyword) => { + const matches = outputString.match(new RegExp(`${keyword}.*`, "gi")); + if (matches) answers.add(...matches); + }); + } catch (e) { + console.error(e); } + + // Convert sets to lists + const answersList = Array.from(answers); + + return answersList; }; const setExample = async (exampleNumber) => { - resetVotingState(); // Reset the voting state before setting the goal and agents - let newGoal = ''; + setIsRunningBoth(false); + resetVotingState(); + setIsRunningBoth(false); + setLeftCompleted(false); + setRightCompleted(false); + setRunBothTriggered(false); + setLeftCodeCollapsed(false); + setRightCodeCollapsed(false); - switch (exampleNumber) { - case 1: - newGoal = 'What is new in California today'; - break; - case 2: - newGoal = 'what was AAPL stock yesterday'; - break; - case 3: - newGoal = 'plot salary and first name given an sql database'; - setIsExample3(true); - try { - const response = await axios.get('https://agent-arena-wuwl.onrender.com/api/db/company', { responseType: 'blob' }); - const file = new File([response.data], 'company.db', { type: 'application/x-sqlite3' }); - setLeftFile(file); - setRightFile(file); - } catch (error) { - toast.error('Error fetching company.db'); - } - break; - default: - break; + let newGoal = ""; + const domains = [ + "finance", + "stocks", + "stock analysis", + "stock comparisons", + "sports news", + "political news", + "financial news", + "weather", + "entertainment news", + "data analysis", + "tech news", + "trivia", + "technology", + "health", + "education", + "creative tasks", + "data analysis", + "everyday life", + "research", + ]; + + const randomDomain = domains[Math.floor(Math.random() * domains.length)]; + console.log(randomDomain); + + if (exampleNumber !== 3) { + setFile(null); // Clear the file if not the financial data example + setLeftFile(null); + setRightFile(null); + } + + if (exampleNumber === "surprise") { + try { + const response = await axios.post( + "https://api.openai.com/v1/chat/completions", + { + model: "gpt-4o-2024-08-06", + temperature: 0.9, + messages: [ + { + role: "system", + content: `You are an assistant that generates random, engaging goals for users to try in an LLM agent comparison platform. + These goals should be interesting, varied, and cover diverse areas such as: + - **Finance:** e.g., "Analyze the performance of the MSFT stock over the last month. Has the price increased or decreased?" + - **Technology:** e.g., "What is the latest news regarding OpenAI's new LLM? What are the model's main contributions. " + - **Health:** e.g., "Design a meal plan for a vegetarian trying to get in at least 100 grams of protein every day." + - **Education:** e.g., "Summarize the key points of the book 'To Kill a Mockingbird' in less than 500 words." + - **Research** e.g., "Tell me about the contributions of Shishir Patil's Gorilla paper" + - **Creative Tasks:** e.g., "Write a short story set in a dystopian future." + - **Data Analysis:** e.g., "Analyze the dataset provided and identify the key trends and patterns." + - **Everyday Life:** e.g., "Organize a weekly schedule that maximizes productivity for remote workers." + - **Weather:** e.g., "What is the weather in Jaipur right now? Is it going to rain today?" + - **Sports News** e.g., "Who is currently first in the Premier League table?" + - **Stock Comparisos** e.g., "Compare the performance of NVDA and Broadcom stocks over the last year." + + The goal that you are trying to achieve should be able to completed by one of our AI agents. Here are the descriptions of the agents available, along with their names as well. In your prompts, do not refer to the agents that are supposed to be executing the goal at all: + ${agentDescriptions} + + Ensure that each goal is specific, clear, and suitable for comparing two different LLM agents. Avoid repeating similar types of goals, especially those related to travel and food. Strive for a balanced distribution across the mentioned categories. + `, + }, + { + role: "user", + content: `Please generate a random goal for the user to use. The goal should be: + - **Clear and Specific:** Precisely defined to allow effective comparison between two LLM agents. + - **Exciting and Diverse:** Cover a range of topics such as finance, technology, health, education, creative tasks, data analysis, and everyday life. + - **Educational or Practical:** Aim to provide value through learning or real-world application. + - **One-Liner:** Concise and to the point. + + **Important:** Avoid goals related to travel and food. Ensure that the generated goal does not fall into these categories and maintains diversity from previous goals. Do not include quotation marks around the goal when returning it. + + In this case, the user is looking for a prompt under the following category: ${randomDomain}. + `, + }, + ], + max_tokens: 100, + }, + { + headers: { + Authorization: `Bearer ${process.env.REACT_APP_OPENAI_API_KEY}`, + }, + } + ); + + newGoal = response.data.choices[0].message.content.trim(); + handleSearch(newGoal); + } catch (error) { + toast.error("Failed to generate a surprise goal. Please try again."); + return; + } + } else { + let isExample3Update = false; + + + + + switch (exampleNumber) { + case 1: + newGoal = "What is new in California today"; + break; + case 2: + newGoal = "what was AAPL stock yesterday"; + break; + case 3: + setIsExample3(true); + setRatingEnabled(false); + console.log(ratingEnabled); + + newGoal = + "using this csv of General Electric financial data, calculate the average return in 2007"; + console.log(isExample3); + + try { + const response = await axios.get( + "https://agent-arena-location.onrender.com/api/db/mydata", + { responseType: "blob" } + ); + const file = new File([response.data], "mydata.csv", { + type: "text/csv", + }); + setFile(file); + // setLeftFile(file); + // setRightFile(file); + } catch (error) { + toast.error("Error fetching mydata.csv"); + } + break; + case 4: // New Research Example case + newGoal = + "Analyze the use of attention mechanisms in transformers for natural language processing, particularly in long-document summarization tasks"; + break; + case 5: + newGoal = + "Automate the process of identifying key patterns in large datasets for predictive analysis."; + break; + default: + break; + } } setGoal(newGoal); @@ -201,151 +793,771 @@ const AgentArena = () => { }; const loadExampleAgents = async (goal) => { - let leftAgentName = ''; - let rightAgentName = ''; + let leftAgentName = ""; + let rightAgentName = ""; + if (!agents.length) { + // Show loading message + toast.info("Loading agents, please wait..."); + + // Reload the page to try fetching agents again after a brief delay + setTimeout(() => { + window.location.reload(); + }, 2000); // Wait 2 seconds before reloading + + return; + } switch (goal) { - case 'What is new in California today': - leftAgentName = 'langchain google-serper search agent (gpt-4o-2024-08-06)'; - rightAgentName = 'langchain brave-search agent (gpt-4o-2024-08-06)'; + case "What is new in California today": + leftAgentName = + "langchain google-serper search agent (gpt-4o-2024-08-06)"; + rightAgentName = "langchain brave-search agent (gpt-4o-2024-08-06)"; + break; + case "what was AAPL stock yesterday": + leftAgentName = + "langchain alpha-vantage stock agent (gpt-4-turbo-2024-04-09)"; + rightAgentName = + "langchain alpha-vantage stock agent (gemini-1.5-flash-001)"; + break; + case "using this csv of General Electric financial data, calculate the average return in 2007": + leftAgentName = "langchain Pandas DataFrame (gpt-4o-2024-08-06)"; + rightAgentName = + "langchain Pandas DataFrame (llama-3.1-405B-instruct)"; + setIsExample3(true); break; - case 'what was AAPL stock yesterday': - leftAgentName = 'langchain alpha-vantage stock agent (gpt-4-turbo-2024-04-09)'; - rightAgentName = 'langchain alpha-vantage stock agent (claude-3-opus-20240229)'; + case "Analyze the use of attention mechanisms in transformers for natural language processing, particularly in long-document summarization tasks": // New Research Example + leftAgentName = "langchain ArXiv Article Fetcher (gpt-4-0613)"; + rightAgentName = + "llamaindex ArXiv Article Fetcher (gpt-4o-2024-08-06)"; break; - case 'plot salary and first name given an sql database': - leftAgentName = 'sql agent plotter langchain (gpt-4o-2024-05-13)'; - rightAgentName = 'sql agent plotter llamaindex (gpt-4o-2024-05-13)'; + case "Automate the process of identifying key patterns in large datasets for predictive analysis.": + leftAgentName = "langchain Shell (claude-3-5-sonnet-20240620)"; + rightAgentName = "langchain Python REPL (gpt-4-turbo-2024-04-09)"; break; default: break; } - const leftAgent = agents.find(agent => agent.name === leftAgentName); - const rightAgent = agents.find(agent => agent.name === rightAgentName); + const leftAgent = agents.find((agent) => agent.name === leftAgentName); + const rightAgent = agents.find((agent) => agent.name === rightAgentName); if (leftAgent && rightAgent) { - setLeftExecutedCode(leftAgent.code.replace('Enter Goal/Prompt Here', goal)); - setRightExecutedCode(rightAgent.code.replace('Enter Goal/Prompt Here', goal)); + setLeftExecutedCode( + leftAgent.code.replace("Enter Goal/Prompt Here", goal) + ); + setRightExecutedCode( + rightAgent.code.replace("Enter Goal/Prompt Here", goal) + ); setLeftAgent(leftAgent); setRightAgent(rightAgent); + setLeftCodeCollapsed(false); + setRightCodeCollapsed(false); } }; return ( -
-

LLM Agent Arena

+ +
+

+ Agent Arena +

+

LMSYS Chatbot Arena X Gorilla 🦍

+

- Welcome to the LLM Agent Arena. Here, you can pit two agents against each other based on a goal you provide. - You can also head to your profile to save prompts for agents and visit the Prompt Hub to see prompts used by - other users along with their ratings. + Welcome to the LLM Agent Arena. Here, you can pit two agents against + each other based on a goal you provide. You can also head to your + profile to save prompts for agents and visit the Prompt Hub to see + prompts used by other users along with their ratings. Ensure your API + keys are configured in your profile for optimal performance.

- - + + {/* Search bar with file upload */} + + + {/* Input for goal */} setGoal(e.target.value)} - style={{ width: '60%', marginRight: '10px' }} + onKeyPress={(e) => { + if (e.key === "Enter") handleSearch(goal); + }} + className="flex-grow-1 me-md-2 mb-2 mb-md-0" + style={{ + borderRadius: "6px", + padding: "10px", + border: "1px solid #ccc", + }} + /> + + {/* File upload button */} + Attach a file} + > + + + + {/* Hidden file input */} + setFile(e.target.files[0])} + style={{ display: "none" }} /> - + + {/* Display uploaded file */} + {/* File upload section */} + {file && ( + + +
+ {/* Display file name */} + + {file.name} + + + {/* Close icon to remove file */} + +
+ +
+ )} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + {!leftAgent || !rightAgent + ? "Please select both agents before running" + : "Agent execution will not take more than 90 seconds."} + + } + > + + + + - -

Agent 1

- - {leftAgent ? ( - { - setLeftExecutedCode(code); - setLeftOutput(output); - setLeftCompleted(true); - }} - output={leftOutput} - allowsFileUpload={leftAgent.allowsFileUpload} - fileUploadMessage={leftAgent.fileUploadMessage} - dbFilePath={leftAgent.allowsFileUpload ? leftFile : null} - isExample3={isExample3} - modificationNeeded={leftAgent.modificationNeeded} - agentName={leftAgent.name} - /> - ) : ( - { - setLeftExecutedCode(code); - setLeftOutput(output); - setLeftCompleted(true); + + + + {showAgentNames ? ( + + ) : null} + {leftAgent ? ( + <> +
+
+ {leftCompleted && ( +
+ > + +
)} - - -

Agent 2

- - {rightAgent ? ( - { - setRightExecutedCode(code); - setRightOutput(output); - setRightCompleted(true); +
+ {((leftCompleted && showLeftRawOutput) || !leftCompleted) && ( + { + setLeftExecutedCode(code); + setLeftOutput(output); + setLeftCompleted(true); + }} + output={leftOutput} + allowsFileUpload={leftAgent.allowsFileUpload} + fileUploadMessage={leftAgent.fileUploadMessage} + dbFilePath={leftAgent.allowsFileUpload ? leftFile : null} + file={leftAgent.allowsFileUpload ? file : null} + onCodeChange={(updatedCode) => setLeftExecutedCode(updatedCode)} + isExample3={isExample3} + modificationNeeded={leftAgent.modificationNeeded} + agentName={leftAgent.name} + averageExecutionTime={leftAgent.averageExecutionTime} + userApiKeys={userApiKeys} + codeCollapsed={leftCodeCollapsed} + setCodeCollapsed={setLeftCodeCollapsed} + isRunningBoth={isRunningBoth} + runBothTriggered={runBothTriggered} + completed={leftCompleted} + /> + )} +
+ {leftCompleted && leftOutput.length > 0 ? ( + <> +

+ {leftOutput.some((block) => block.includes("Final Answer")) + ? "Final Answer from Agent 1:" + : "Full Output from Agent 1:"} +

+ + {/* Scrollable container for left agent output */} +
+ {leftOutput.some((block) => block.includes("Final Answer")) + ? ( + <> + {/* Display Final Answer */} + {leftOutput + .filter((block) => block.includes("Final Answer")) + .map((block, index) => ( +
+
+
+ ))} + + {/* Combine all blocks after "Final Answer" into one scrollable block */} +
+ block.includes("Final Answer") + ) + 1 + ) + .filter((block) => block.trim() !== "") + .join(""), }} - output={rightOutput} - allowsFileUpload={rightAgent.allowsFileUpload} - fileUploadMessage={rightAgent.fileUploadMessage} - dbFilePath={rightAgent.allowsFileUpload ? rightFile : null} - isExample3={isExample3} - modificationNeeded={rightAgent.modificationNeeded} - agentName={rightAgent.name} /> - ) : ( - { - setRightExecutedCode(code); - setRightOutput(output); - setRightCompleted(true); + + ) + : ( + /* Combine all blocks into one scrollable block if there is no "Final Answer" */ +
+ )} +
+ +) : null} + + + + ) : null} + + + + + {showAgentNames ? ( + + ) : null} + {rightAgent ? ( + <> +
+
+ {rightCompleted && ( +
+ > + +
)} - +
+ {((rightCompleted && showRightRawOutput) || !rightCompleted) && ( + { + setRightExecutedCode(code); + setRightOutput(output); + setRightCompleted(true); + }} + output={rightOutput} + allowsFileUpload={rightAgent.allowsFileUpload} + fileUploadMessage={rightAgent.fileUploadMessage} + dbFilePath={rightAgent.allowsFileUpload ? rightFile : null} + file={rightAgent.allowsFileUpload ? file : null} + onCodeChange={(updatedCode) => setRightExecutedCode(updatedCode)} + isExample3={isExample3} + modificationNeeded={rightAgent.modificationNeeded} + agentName={rightAgent.name} + averageExecutionTime={rightAgent.averageExecutionTime} + userApiKeys={userApiKeys} + codeCollapsed={rightCodeCollapsed} + setCodeCollapsed={setRightCodeCollapsed} + isRunningBoth={isRunningBoth} + runBothTriggered={runBothTriggered} + completed={rightCompleted} + /> + )} +
+ {rightCompleted && rightOutput.length > 0 ? ( + <> +

+ {rightOutput.some((block) => block.includes("Final Answer")) + ? "Final Answer from Agent 2:" + : "Full Output from Agent 2:"} +

+ + {/* Scrollable container for right agent output */} +
+ {rightOutput.some((block) => block.includes("Final Answer")) + ? ( + <> + {/* Display Final Answer */} + {rightOutput + .filter((block) => block.includes("Final Answer")) + .map((block, index) => ( +
+
+
+ ))} + + {/* Combine all blocks after "Final Answer" into one scrollable block */} +
+ block.includes("Final Answer") + ) + 1 + ) + .filter((block) => block.trim() !== "") + .join(""), + }} + /> + + ) + : ( + /* Combine all blocks into one scrollable block if there is no "Final Answer" */ +
+ )} +
+ +) : null} + + + + + ) : null} + + - {hasVoted && isLoggedIn && ( + {!isLoggedIn && ( + + + You can share the result after voting! + } + > + + + + + + + )} + {isLoggedIn && ( - + You can share the result after voting! + } + > + + + + )} diff --git a/agent-arena/client/src/components/AgentDropdown.js b/agent-arena/client/src/components/AgentDropdown.js index 0492aad7ec..721336b89f 100644 --- a/agent-arena/client/src/components/AgentDropdown.js +++ b/agent-arena/client/src/components/AgentDropdown.js @@ -59,6 +59,10 @@ const AgentDropdown = ({ agents, selectedAgent, onSelect }) => { indicatorSeparator: () => ({ display: 'none', // Remove the separator for a cleaner look }), + input: (provided) => ({ + ...provided, + color: theme === 'dark' ? '#ccc' : '#000', // Lighter text color for dark mode + }), }; return ( diff --git a/agent-arena/client/src/components/CodeEditor.js b/agent-arena/client/src/components/CodeEditor.js index 6e7505b296..d5ab2ce13b 100644 --- a/agent-arena/client/src/components/CodeEditor.js +++ b/agent-arena/client/src/components/CodeEditor.js @@ -2,13 +2,36 @@ import React, { useState, useEffect, useContext } from 'react'; import AceEditor from 'react-ace'; import 'ace-builds/src-noconflict/mode-python'; import 'ace-builds/src-noconflict/theme-monokai'; -import 'ace-builds/src-noconflict/theme-github'; // Add this for light mode +import 'ace-builds/src-noconflict/theme-github'; import axios from 'axios'; -import { Card, Button, Spinner, Form } from 'react-bootstrap'; +import { Card, Button, Spinner, Form, Collapse } from 'react-bootstrap'; import StaticFileInput from './StaticFileInput'; import { ThemeContext } from '../App'; +import { AnsiUp } from 'ansi_up'; -const CodeEditor = ({ agentId, initialCode, onExecute, output: initialOutput, allowsFileUpload, fileUploadMessage, dbFilePath, isExample3, modificationNeeded, agentName }) => { +const ansiUp = new AnsiUp(); + +const CodeEditor = ({ + agentId, + initialCode, + onExecute, + output: initialOutput, + allowsFileUpload, + fileUploadMessage, + dbFilePath, + isExample3, + modificationNeeded, + agentName, + averageExecutionTime, + file, + userApiKeys, + codeCollapsed, + setCodeCollapsed, + isRunningBoth, + runBothTriggered, + onCodeChange, + completed, +}) => { const { theme } = useContext(ThemeContext); const [code, setCode] = useState(initialCode || ''); const [output, setOutput] = useState(initialOutput || ''); @@ -18,21 +41,34 @@ const CodeEditor = ({ agentId, initialCode, onExecute, output: initialOutput, al const [dbFileName, setDbFileName] = useState(dbFilePath ? dbFilePath.name : ''); const [dbFile, setDbFile] = useState(dbFilePath ? dbFilePath : null); const [generalFileName, setGeneralFileName] = useState(''); - const [generalFile, setGeneralFile] = useState(null); + const [generalFile, setGeneralFile] = useState(file ? file : null); const [countdown, setCountdown] = useState(0); const [generatedFiles, setGeneratedFiles] = useState([]); const [imageSrc, setImageSrc] = useState(''); const [imageLoading, setImageLoading] = useState(false); const [error, setError] = useState(null); + const [isRunning, setIsRunning] = useState(false); + const [showRunButton, setShowRunButton] = useState(false); + const [eventSource, setEventSource] = useState(null); // Added state variable for EventSource + + + useEffect(() => { - setCode(initialCode); + setCode(initialCode || ''); }, [initialCode]); useEffect(() => { - setOutput(initialOutput); + setOutput(initialOutput || ''); }, [initialOutput]); + useEffect(() => { + if (file) { + setGeneralFile(file); + setGeneralFileName(file.name); + } + }, [file]); + useEffect(() => { if (dbFilePath && dbFilePath instanceof File) { setDbFile(dbFilePath); @@ -40,6 +76,20 @@ const CodeEditor = ({ agentId, initialCode, onExecute, output: initialOutput, al } }, [dbFilePath]); + useEffect(() => { + if (allowsFileUpload && file) { + setGeneralFile(file); + setGeneralFileName(file.name); + } + }, [allowsFileUpload, file]); + + useEffect(() => { + if (isExample3 && file) { + setGeneralFile(file); + setGeneralFileName(file.name); + } + }, [isExample3, file]); + useEffect(() => { let timer; if (countdown > 0) { @@ -54,154 +104,233 @@ const CodeEditor = ({ agentId, initialCode, onExecute, output: initialOutput, al const handleCodeChange = (newCode) => { setCode(newCode); + if (onCodeChange) { + onCodeChange(newCode); + } }; + useEffect(() => { + if (isExample3) { + setGeneralFileName('mydata.csv'); + } + }, [isExample3]); + + useEffect(() => { + if (runBothTriggered && isRunningBoth && !completed) { + const avgExecTime = parseInt(averageExecutionTime, 10); + let countdownTime = avgExecTime >= 5 ? avgExecTime : 40; + setCountdown(countdownTime); + setShowRunButton(true); + setLoading(true); + } else if (completed) { + setLoading(false); + setCountdown(0); + setShowRunButton(false); + } + }, [runBothTriggered, isRunningBoth, completed, averageExecutionTime]); + const handleDbFileChange = (event) => { const file = event.target.files[0]; setDbFile(file); setDbFileName(file.name); - console.log("DB file set:", file); }; const handleGeneralFileChange = (event) => { const file = event.target.files[0]; setGeneralFileName(file.name); setGeneralFile(file); - console.log("General file set:", file); }; + useEffect(() => { + if (generalFileName && code.includes('FILE_NAME')) { + const updatedCode = code.replace(/FILE_NAME/g, generalFileName); + setCode(updatedCode); + if (onCodeChange) { + onCodeChange(updatedCode); + } + } + }, [generalFileName, code]); + const handleRunCode = () => { + // Close any existing EventSource + if (eventSource) { + eventSource.close(); + setEventSource(null); + } + setLoading(true); - setCountdown(20); + setIsRunning(true); + setOutput(''); + setCodeCollapsed(true); + + const avgExecTime = parseInt(averageExecutionTime, 10); + let countdownTime = avgExecTime >= 5 ? avgExecTime : 40; + setCountdown(countdownTime); + const formData = new FormData(); formData.append('code', code); formData.append('agentId', agentId); - console.log(agentName); - console.log(dbFile); - if (["sql agent plotter llamaindex (gpt-4o-2024-08-06)", "sql agent plotter langchain (gpt-4o-2024-08-06)", - "sql agent plotter llamaindex (gpt-4o-2024-05-13)", "sql agent plotter langchain (gpt-4o-2024-05-13)", - "sql agent plotter llamaindex (gpt-4-turbo-2024-04-09)", "sql agent plotter langchain (gpt-4-turbo-2024-04-09)", - "sql agent plotter llamaindex (gpt-4-0613)", "sql agent plotter langchain (gpt-4-0613)", - "sql agent plotter llamaindex (claude-3-5-sonnet-20240620)", "sql agent plotter langchain (claude-3-5-sonnet-20240620)", - "sql agent plotter llamaindex (claude-3-opus-20240229)", "sql agent plotter langchain (claude-3-opus-20240229)", - "sql agent plotter llamaindex (claude-3-haiku-20240307)", "sql agent plotter langchain (claude-3-haiku-20240307)", - "anthropic sql query"].includes(agentName)) { - console.log('hi'); - if (dbFile) { - formData.append('db_file', dbFile); - console.log("Appending db_file to formData:", dbFile); - } - } else if (generalFile) { - formData.append('general_file', generalFile); - console.log("Appending general_file to formData:", generalFile); - } - // Log the FormData to ensure it has the correct keys and values - for (let [key, value] of formData.entries()) { - console.log(key, value); + // File handling logic (unchanged) + + if (userApiKeys) { + Object.keys(userApiKeys).forEach((key) => { + formData.append(key, userApiKeys[key]); + }); } - axios.post('https://agent-arena-wuwl.onrender.com/api/jobs/create', formData, { - headers: { - 'Content-Type': 'multipart/form-data' + axios + .post('https://agent-arena-location.onrender.com/api/jobs/create', formData, { + headers: { 'Content-Type': 'multipart/form-data' }, + }) + .then((response) => { + setJobId(response.data.jobId); + streamJobOutput(response.data.jobId); + }) + .catch((error) => { + setOutput(error.response?.data?.error || 'An error occurred'); + setLoading(false); + setIsRunning(false); + }); + }; + + const streamJobOutput = (jobId) => { + const es = new EventSource(`https://agent-arena-location.onrender.com/api/jobs/${jobId}/stream`); + setEventSource(es); // Store the EventSource + + let fullOutput = ''; + + es.onmessage = (event) => { + let processedOutput = event.data; + const coloredHtml = ansiUp.ansi_to_html(processedOutput); + fullOutput += coloredHtml + '\n'; + setOutput((prevOutput) => prevOutput + coloredHtml + '\n'); + }; + + es.onerror = () => { + es.close(); + setLoading(false); + setIsRunning(false); + setCountdown(0); + if (onExecute) { + onExecute(code, fullOutput); } - }) - .then(response => { - setJobId(response.data.jobId); - pollJobStatus(response.data.jobId); - }) - .catch(error => { - setOutput(error.response?.data?.error || 'An error occurred'); + }; + + es.addEventListener('end', () => { + es.close(); setLoading(false); + setIsRunning(false); + setCountdown(0); + if (onExecute) { + onExecute(code, fullOutput); + } }); }; - const pollJobStatus = (jobId) => { - const interval = setInterval(() => { - axios.get(`https://agent-arena-wuwl.onrender.com/api/jobs/${jobId}/status`) - .then(response => { - setOutput(response.data.output); - setGeneratedFiles(response.data.generated_files); - - if (response.data.status === 'completed' || response.data.status === 'error') { - clearInterval(interval); - setLoading(false); - setCountdown(0); - - const base64Pattern = /"content":"([A-Za-z0-9+/=]+)"/; - const match = response.data.output.match(base64Pattern); - if (match) { - const base64String = match[1]; - const imageSrc = `data:image/png;base64,${base64String}`; - setImageSrc(imageSrc); - setImageLoading(true); - } - - if (onExecute) { - onExecute(code, response.data.output); - } - } - - if (response.data.currentInput) { - setInput(response.data.currentInput); - } - }) - .catch(error => { - console.error(error); - clearInterval(interval); - setLoading(false); - setCountdown(0); - }); - }, 1000); - }; - const handleProvideInput = () => { - axios.post(`https://agent-arena-wuwl.onrender.com/api/jobs/${jobId}/input`, { input }) - .then(response => { + axios + .post(`https://agent-arena-location.onrender.com/api/jobs/${jobId}/input`, { input }) + .then((response) => { setInput(''); }) - .catch(error => { - console.error(error); + .catch((error) => { + console.error('Error providing input:', error); }); }; + // **Add useEffect to reset state when agentId changes** + useEffect(() => { + // Reset code to initialCode + setCode(initialCode || ''); + // Reset output + setOutput(initialOutput || ''); + // Reset loading and execution states + setLoading(false); + setIsRunning(false); + setCountdown(0); + setShowRunButton(false); + // Close any existing EventSource connections + if (eventSource) { + eventSource.close(); + setEventSource(null); + } + // Reset jobId + setJobId(null); + // Reset files if necessary + setDbFile(dbFilePath ? dbFilePath : null); + setDbFileName(dbFilePath ? dbFilePath.name : ''); + setGeneralFile(file ? file : null); + setGeneralFileName(file ? file.name : ''); + // Reset any other state variables as needed + }, [agentId]); + + // **Cleanup on component unmount** + useEffect(() => { + return () => { + if (eventSource) { + eventSource.close(); + } + }; + }, [eventSource]); + return ( - {agentId && ( -
- {isExample3 ? "Add your API keys and run the code" : (modificationNeeded ? "Modify the task description in the code and add your API keys" : "Add your API keys and run the code")} -
- )} - - {allowsFileUpload && ( - - {fileUploadMessage} - {isExample3 ? ( - + {agentId && !isRunning && !isRunningBoth && ( +
+ {isExample3 || !modificationNeeded ? ( + <> + We have populated API keys for agents, but for the best experience, and if you encounter rate limits, + pass your API keys and run the code. You can add API keys here. + ) : ( - - )} - {["sql agent plotter langchain (gpt-4o-2024-05-13)", "sql agent plotter llamaindex (gpt-4o-2024-05-13)"].includes(agentName) && dbFileName &&
{}
} - - )} -
-
+ )} + {completed && ( + + )} + +
+ +
+
+
+ {showRunButton && ( +
+ +
+ )}
{input && (
@@ -218,16 +347,34 @@ const CodeEditor = ({ agentId, initialCode, onExecute, output: initialOutput, al
)} - - {output} - + + {allowsFileUpload && ( + <> + {/* Static file input that automatically shows the file name */} + {!generalFile && ( +
+ Warning: You must upload a file for this agent to run. +
+ )} + + )} + + {imageSrc && (
Generated Base64 Image diff --git a/agent-arena/client/src/components/ContactUs.js b/agent-arena/client/src/components/ContactUs.js new file mode 100644 index 0000000000..5570569f16 --- /dev/null +++ b/agent-arena/client/src/components/ContactUs.js @@ -0,0 +1,140 @@ +import React, { useState, useContext } from 'react'; +import { Container, Row, Col, Form, Button } from 'react-bootstrap'; +import { ThemeContext } from '../App'; +import { toast } from 'react-toastify'; +import axios from 'axios'; + +const ContactUs = () => { + const [formData, setFormData] = useState({ name: '', email: '', message: '' }); + const { theme } = useContext(ThemeContext); + + const handleInputChange = (e) => { + const { name, value } = e.target; + setFormData({ ...formData, [name]: value }); + }; + + const handleSubmit = async (e) => { + e.preventDefault(); + + try { + const response = await axios.post('https://agent-arena.vercel.app/api/contact/submit', formData); + + if (response.status === 200) { + toast.success('Your inquiry has been sent. We will get back to you soon!'); + setFormData({ name: '', email: '', message: '' }); + } + } catch (error) { + console.error('Error submitting inquiry:', error); + toast.error('There was an error sending your inquiry. Please try again later.'); + } + }; + + const styles = { + container: { + paddingTop: '3rem', + paddingBottom: '3rem', + backgroundColor: theme === 'dark' ? '#1a1a2e' : '#f8f9fa', + color: theme === 'dark' ? '#e0e0e0' : '#333', + minHeight: 'calc(100vh - 60px)', + }, + formContainer: { + backgroundColor: theme === 'dark' ? '#242e42' : '#ffffff', + padding: '2rem', + borderRadius: '10px', + boxShadow: theme === 'dark' ? '0 4px 6px rgba(0, 0, 0, 0.2)' : '0 4px 6px rgba(0, 0, 0, 0.1)', + }, + title: { + color: theme === 'dark' ? '#81a1c1' : '#2c3e50', + marginBottom: '1.5rem', + }, + description: { + color: theme === 'dark' ? '#d8dee9' : '#555', + marginBottom: '2rem', + }, + label: { + color: theme === 'dark' ? '#81a1c1' : '#2c3e50', + fontWeight: 'bold', + }, + input: { + backgroundColor: theme === 'dark' ? '#ccdaf0' : '#f8f9fa', + color: theme === 'dark' ? '#333' : '#333', + border: theme === 'dark' ? '1px solid #3b4252' : '1px solid #ced4da', + }, + button: { + backgroundColor: theme === 'dark' ? '#5e81ac' : '#2c3e50', + borderColor: theme === 'dark' ? '#5e81ac' : '#2c3e50', + color: '#ffffff', + padding: '0.5rem 2rem', + fontSize: '1.1rem', + marginTop: '1rem', + transition: 'all 0.3s ease', + }, + }; + + return ( +
+ + + +
+

Contact Us

+

+ If you have any questions, suggestions, or would like to contribute agents or models, please fill out the form below, and we'll get back to you shortly. +

+ +
+ + Your Name + + + + + Your Email + + + + + Your Message + + + +
+ +
+
+
+ +
+
+
+ ); +}; + +export default ContactUs; \ No newline at end of file diff --git a/agent-arena/client/src/components/FAQ.js b/agent-arena/client/src/components/FAQ.js new file mode 100644 index 0000000000..4ec8895feb --- /dev/null +++ b/agent-arena/client/src/components/FAQ.js @@ -0,0 +1,134 @@ +import React from 'react'; +import { Container, Row, Col, Accordion } from 'react-bootstrap'; +import { Analytics } from "@vercel/analytics/react"; + +const FAQ = () => { + return ( + + +

FAQ

+

+ Here you'll find answers to some frequently asked questions about the LLM Agent Arena, its features, and how to get the most out of the platform. +

+ + + + What is LLM Agent Arena? + + The LLM Agent Arena is a platform that allows users to compare two different LLM agents based on specific goals. You can select agents, run their code, and evaluate their performance to see which one meets the goal better. + + + + + How do I select and compare agents? + + You can enter a goal in the search bar, and our system will automatically assign two random agents that are best suited to achieve the goal. However, you can also use the dropdown menus labeled "Agent 1" and "Agent 2" to change the agents manually. After selecting or modifying the agents, you can run them to compare their outputs and vote on which one performs better. + + + + + + What are examples of goals I can use to compare agents? + + The platform provides a variety of example goals, such as: +
    +
  • “What was AAPL stock yesterday?”
  • +
  • “Summarize an interesting article about cats.”
  • +
  • “Find cheap hotels in Austin, Texas.”
  • +
+ You can also create your own goal by entering a specific task in the search bar. +
+
+ + + What is the Prompt Hub? + + The Prompt Hub is a feature that allows users to save and share prompts used in the arena. You can view prompts from other users, along with the agents and results they used. This is a great way to explore different goals and see which agents work best for specific tasks. + + + + + How does the rating system work? + + After running both agents, you will be able to rate their performance by choosing whether Agent 1, Agent 2, both, or neither performed better. Your rating helps improve the overall rankings of agents in the leaderboard. + + + + + What is the Leaderboard? + + The Leaderboard is a comprehensive ranking system that showcases the performance of AI agents, models, tools, and frameworks. It uses an ELO-like rating system derived from battle-style competitions between agents across various categories. The Leaderboard doesn't just rank agents as a whole, but also leverages battle information to evaluate and rank individual components such as models (e.g., OpenAI, Anthropic), tools (categorized by function), and frameworks (e.g., LangChain, LlamaIndex). This granular approach provides insights into what makes an effective AI agent and helps users understand which underlying technologies are driving success in different domains. + + + + + How do I save prompts and view my saved prompts? + + After running agents and voting, you can save the prompt for future use by heading to your profile and selecting "Save Prompt." All saved prompts will be available in your profile under the "Saved Prompts" section. + + + + + How can I use my own API keys in the arena? + + For the best experience, it is recommended to add your own API keys for specific agents. After logging in, you can configure your API keys in your profile page by navigating to the "API Keys" section. These keys will then be automatically used when running the agents. + + + + + Is there a way to share results with others? + + Yes! After voting, you can share your session by generating a shareable link. This link will allow others to view the agents you used, the prompt, and the output results. You can find the shareable link in your saved prompts or after running agents. + + + + + + How can people contribute agents or models? + + If you'd like to contribute agents or models to the LLM Agent Arena, we welcome your contributions! You can reach out to us via our Contact Us page to discuss the agents or models you'd like to add. Our team will review your submission and get back to you. + + + + + What models do we consider? + + We currently have support for models across various providers, including OpenAI, Anthropic, Google Gemini, Llama, and Mistral. Here are the models we have integrated: +
    +
  • gpt-4o-2024-08-06, gpt-4o-2024-05-13, gpt-4-turbo-2024-04-09, gpt-4-0613
  • +
  • claude-3-5-sonnet-20240620, claude-3-opus-20240229, claude-3-haiku-20240307
  • +
  • gemini-1.5-pro-001, gemini-1.5-flash-001
  • +
  • open-mixtral-8x7b, mistral-large-2407, open-mixtral-8x22b
  • +
  • llama-3.1-405B-instruct, llama-3.1-8B-instruct, llama-3.1-70B-instruct
  • +
  • llama-3.1-sonar-small-128k-online, llama-3.1-sonar-large-128k-online, llama-3.1-sonar-huge-128k-online
  • +
+
+
+ + + What agents do we consider? + + We support agents from various frameworks such as: + + Some of our featured agents use various tools like Brave API, Yahoo Finance, and more. We also source and modify example agents from the respective frameworks. + Additionally, we have general-purpose assistants like OpenAI’s assistants (e.g., code interpreting, file reading), and tool/API-based examples from Anthropic and Perplexity. + + + + + Have more questions? + + If you have more questions, feel free to reach out to us via email at agentarenateam@gmail.com or use our Contact Us form. + + +
+
+ ); +}; + +export default FAQ; diff --git a/agent-arena/client/src/components/Leaderboard.js b/agent-arena/client/src/components/Leaderboard.js index 1216c304a4..c58a273f4a 100644 --- a/agent-arena/client/src/components/Leaderboard.js +++ b/agent-arena/client/src/components/Leaderboard.js @@ -1,10 +1,13 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useContext } from 'react'; import axios from 'axios'; import { Container, Card } from 'react-bootstrap'; import Select from 'react-select'; +import { Analytics } from "@vercel/analytics/react"; +import { ThemeContext } from "../App"; + // Filter colors for agents based on their categories -const filterColors = { +const agentFilterColors = { AI: { normal: '#a8e6cf', hover: '#91d4b7' }, Data: { normal: '#dcedc1', hover: '#c6d7a8' }, Integration: { normal: '#ffd3b6', hover: '#ffbfa0' }, @@ -14,7 +17,19 @@ const filterColors = { Search: { normal: '#c5cae9', hover: '#9fa8da' }, Automation: { normal: '#ffccbc', hover: '#ffab91' }, Research: { normal: '#ffe0b2', hover: '#ffcc80' }, - Analytics: { normal: '#f8bbd0', hover: '#e1a2b8' }, +}; + +// Filter colors for tools based on their categories +const toolFilterColors = { + Automation: { normal: '#ffccbc', hover: '#ffab91' }, + Communication: { normal: '#ffaaa5', hover: '#ff918f' }, + Data: { normal: '#dcedc1', hover: '#c6d7a8' }, + Database: { normal: '#ff8b94', hover: '#ff6d78' }, + Finance: { normal: '#a2d5f2', hover: '#8bc3de' }, + General: { normal: '#ffccbc', hover: '#ffab91' }, // General category + Integration: { normal: '#ffd3b6', hover: '#ffbfa0' }, + Research: { normal: '#ffe0b2', hover: '#ffcc80' }, + Search: { normal: '#c5cae9', hover: '#9fa8da' }, }; // Framework-specific colors with hover states @@ -27,16 +42,56 @@ const frameworkColors = { 'anthropic tool use': { normal: '#f7cac9', hover: '#f4b0a9' }, }; -// Adjusted model-specific colors for GPT and Claude +// Adjusted model-specific colors const modelColors = { - gpt: { normal: '#9bc2c4', hover: '#76c776' }, // More desaturated green - claude: { normal: '#ffbfa0', hover: '#ff7f50' }, // Adjusted orange + OpenAI: { normal: '#9bc2c4', hover: '#76c776' }, // OpenAI (gpt) + Anthropic: { normal: '#ffbfa0', hover: '#ff7f50' }, // Anthropic (claude) + Perplexity: { normal: '#A9A9A9', hover: '#808080' }, // Perplexity (sonar) + 'Mistral AI': { normal: '#FFA500', hover: '#FF8C00' }, // Mistral (mistral) + Google: { normal: '#4285F4', hover: '#357ae8' }, // Google (gemini) + Meta: { normal: '#4267B2', hover: '#365899' }, // Meta (llama) }; -// Unified tool color with hover state -const toolColor = { normal: '#87ceeb', hover: '#6495ed' }; // Light Blue for Tools +// Provider options for filtering models by provider with colors in the dropdown +const providerOptions = Object.keys(modelColors).map(provider => ({ + value: provider, + label: ( + + + {provider} + + ), +})); + +const agentCategoryOptions = Object.keys(agentFilterColors).map(cat => ({ + value: cat, + label: ( + + + {cat} + + ), +})); -const categoryOptions = Object.keys(filterColors).map(cat => ({ +const toolCategoryOptions = Object.keys(toolFilterColors).map(cat => ({ value: cat, label: ( @@ -46,7 +101,7 @@ const categoryOptions = Object.keys(filterColors).map(cat => ({ width: '12px', height: '12px', borderRadius: '50%', - backgroundColor: filterColors[cat].normal, + backgroundColor: toolFilterColors[cat].normal, marginRight: '8px', }} > @@ -110,41 +165,43 @@ const LeaderboardTable = ({ title, data, sortBy }) => { return (

{title}

-
10 ? 'scroll' : 'auto' }}> {/* Set max height and enable scroll */} +
10 ? 'scroll' : 'auto' }}> - {/* Numbering header */} + - + {sortBy === 'agents' && <> - - + } - {data.map((item, index) => { // Display only the top 10 items - let backgroundColor = '#2c3e50'; // Default background color - let hoverColor = '#34495e'; // Default hover color + {data.map((item, index) => { + let backgroundColor = '#2c3e50'; + let hoverColor = '#34495e'; if (sortBy === 'agents') { - backgroundColor = filterColors[item.category]?.normal || backgroundColor; - hoverColor = filterColors[item.category]?.hover || hoverColor; - } else if (sortBy === 'models') { - const modelType = item.name.startsWith('claude') ? 'claude' : 'gpt'; - backgroundColor = modelColors[modelType]?.normal || backgroundColor; - hoverColor = modelColors[modelType]?.hover || hoverColor; + backgroundColor = agentFilterColors[item.category]?.normal || backgroundColor; + hoverColor = agentFilterColors[item.category]?.hover || hoverColor; } else if (sortBy === 'tools') { - backgroundColor = toolColor.normal; - hoverColor = toolColor.hover; + backgroundColor = toolFilterColors[item.category]?.normal || backgroundColor; + hoverColor = toolFilterColors[item.category]?.hover || hoverColor; + } else if (sortBy === 'models') { + backgroundColor = modelColors[item.provider]?.normal || backgroundColor; + hoverColor = modelColors[item.provider]?.hover || hoverColor; } else if (sortBy === 'frameworks') { backgroundColor = frameworkColors[item.name.toLowerCase()]?.normal || backgroundColor; hoverColor = frameworkColors[item.name.toLowerCase()]?.hover || hoverColor; } + const successRate = item.passCount + item.failCount > 0 + ? ((item.passCount / (item.passCount + item.failCount))).toFixed(2) + : 'N/A'; + return ( { onMouseEnter={(e) => e.currentTarget.style.backgroundColor = hoverColor} onMouseLeave={(e) => e.currentTarget.style.backgroundColor = backgroundColor} > - {/* Numbering each row */} + - + {/* Display vote percentage */} {sortBy === 'agents' && <> - - + } ); @@ -171,20 +227,23 @@ const LeaderboardTable = ({ title, data, sortBy }) => { ); }; - const Leaderboard = () => { const [agents, setAgents] = useState([]); const [models, setModels] = useState([]); const [tools, setTools] = useState([]); const [frameworks, setFrameworks] = useState([]); - const [category, setCategory] = useState('Search'); // Set default to 'Search' - const [sortBy, setSortBy] = useState('skill'); + const [category, setCategory] = useState('Finance'); // Default category + const [toolCategory, setToolCategory] = useState('Search'); // Tool category + const [provider, setProvider] = useState(''); // Provider filter + const [sortBy, setSortBy] = useState('skill'); // Sort by field + const { theme } = useContext(ThemeContext); + useEffect(() => { const fetchData = async () => { const agentsResponse = await axios.get(`https://agent-arena.vercel.app/api/leaderboard?category=${category}&sortBy=${sortBy}`); - const modelsResponse = await axios.get(`https://agent-arena.vercel.app/api/leaderboard/models?category=${category}&sortBy=${sortBy}`); - const toolsResponse = await axios.get(`https://agent-arena.vercel.app/api/leaderboard/tools?category=${category}&sortBy=${sortBy}`); + const modelsResponse = await axios.get(`https://agent-arena.vercel.app/api/leaderboard/models?sortBy=${sortBy}&provider=${provider}`); + const toolsResponse = await axios.get(`https://agent-arena.vercel.app/api/leaderboard/tools?category=${toolCategory}&sortBy=${sortBy}`); const frameworksResponse = await axios.get(`https://agent-arena.vercel.app/api/leaderboard/frameworks?category=${category}&sortBy=${sortBy}`); setAgents(agentsResponse.data); setModels(modelsResponse.data); @@ -193,34 +252,92 @@ const Leaderboard = () => { }; fetchData(); - }, [category, sortBy]); + }, [category, toolCategory, provider, sortBy]); const handleCategoryChange = (selectedOption) => { setCategory(selectedOption ? selectedOption.value : ''); }; + const handleToolCategoryChange = (selectedOption) => { + setToolCategory(selectedOption ? selectedOption.value : ''); + }; + + const handleProviderChange = (selectedOption) => { + setProvider(selectedOption ? selectedOption.value : ''); + }; + const handleSortByChange = (selectedOption) => { setSortBy(selectedOption ? selectedOption.value : 'skill'); }; return ( -

Agent Leaderboard

+

Leaderboard

+

+ The Leaderboard ranks AI agents, models, tools, and frameworks using ELO-style ratings from battles. + It offers insights into agent capabilities across various categories and leverages battle data to evaluate individual agent components, + providing a comprehensive view of agent performance in different domains. +

+ {/* Tools and Models Leaderboards Side by Side */} +
+
+
+ + option.value === 'Search')} + /> +
+ +
+
+ + {/* Frameworks Leaderboard */} + + + {/* Dropdowns for Agents Leaderboard */}
- + {
{/* Agents Leaderboard */} - + + - -); + + @media (min-width: 768px) { + .leaderboard-container { + flex-direction: row; + justify-content: space-between; + } + + .leaderboard-item { + width: 48%; + } + } + `} + + ); }; export default Leaderboard; diff --git a/agent-arena/client/src/components/Login.js b/agent-arena/client/src/components/Login.js index 48e80d1a34..39ee833b45 100644 --- a/agent-arena/client/src/components/Login.js +++ b/agent-arena/client/src/components/Login.js @@ -2,6 +2,8 @@ import React, { useState } from 'react'; import axios from 'axios'; import { useNavigate, Link } from 'react-router-dom'; import { Form, Button, Container } from 'react-bootstrap'; +import {toast } from 'react-toastify'; +import 'react-toastify/dist/ReactToastify.css'; const Login = ({ onLogin }) => { const [formData, setFormData] = useState({ email: '', password: '' }); @@ -20,6 +22,11 @@ const Login = ({ onLogin }) => { navigate('/'); } catch (error) { console.error('Error logging in', error); + if (error.response && error.response.status === 400) { + toast.error('Invalid email or password'); + } else { + toast.error('An error occurred during login'); + } } }; @@ -41,6 +48,9 @@ const Login = ({ onLogin }) => {

Don't have an account? Sign up here

+

+ Forgot Password? +

); }; diff --git a/agent-arena/client/src/components/MonitoringDashboard.js b/agent-arena/client/src/components/MonitoringDashboard.js new file mode 100644 index 0000000000..6b6027ad69 --- /dev/null +++ b/agent-arena/client/src/components/MonitoringDashboard.js @@ -0,0 +1,159 @@ +import React, { useEffect, useState } from 'react'; +import axios from 'axios'; +import { Container, Table, Card, Spinner, Button, Form } from 'react-bootstrap'; + +const MonitoringDashboard = () => { + const [streamData, setStreamData] = useState([]); + const [errorSuccessStats, setErrorSuccessStats] = useState({}); + const [failingAgents, setFailingAgents] = useState([]); + const [totalRatings, setTotalRatings] = useState(0); + const [loading, setLoading] = useState(true); + const [filterErrors, setFilterErrors] = useState(false); + const [passcode, setPasscode] = useState(''); + const [authenticated, setAuthenticated] = useState(false); + + const apiUrl = 'https://agent-arena.vercel.app/api/monitoring'; + + // Function to check the passcode locally (not sent to backend) + const handlePasscodeSubmit = (e) => { + e.preventDefault(); + const correctPasscode = process.env.REACT_APP_DASHBOARD_PASSCODE; + + if (passcode === correctPasscode) { + setAuthenticated(true); + fetchData(); // Fetch data after successful passcode entry + } else { + alert('Invalid passcode'); + } + }; + + // Fetch monitoring data after authentication + const fetchData = async () => { + try { + const [statsRes, agentsRes, ratingsRes] = await Promise.all([ + axios.get(`${apiUrl}/stats`), + axios.get(`${apiUrl}/failing-agents`), + axios.get(`${apiUrl}/total-ratings`), + ]); + + setErrorSuccessStats(statsRes.data); + setFailingAgents(agentsRes.data); + setTotalRatings(ratingsRes.data.totalRatings); + setLoading(false); + } catch (error) { + console.error('Error fetching data', error); + } + }; + + // Streaming executed code and errors after authentication + useEffect(() => { + if (authenticated) { + const eventSource = new EventSource(`${apiUrl}/stream-data`); + + eventSource.onmessage = (event) => { + setStreamData((prevData) => [JSON.parse(event.data), ...prevData]); // Most recent at the top + }; + + eventSource.onerror = (error) => { + console.error('Error streaming data', error); + eventSource.close(); + }; + + return () => { + eventSource.close(); + }; + } + }, [authenticated]); + + if (!authenticated) { + return ( + +

Enter Dashboard Passcode

+
+ + setPasscode(e.target.value)} + /> + + + +
+ ); + } + + if (loading) return ; + + const filteredData = filterErrors + ? streamData.filter((execution) => !execution.isSuccess) + : streamData; + + return ( + +

Monitoring Dashboard

+ + + +

Error/Success Rates (Last 30 Minutes)

+

Success Rate: {errorSuccessStats.successRate}%

+

Fail Rate: {errorSuccessStats.failRate}%

+
+
+ + + +

Agents Failing the Most

+
    + {failingAgents.map((agent) => ( +
  • + {agent.name} (Failures: {agent.failCount}) +
  • + ))} +
+
+
+ + + +

Total Ratings

+

Total number of ratings: {totalRatings}

+
+
+ + + +

Real-time Execution Status

+
+ +
## Name Skill ParameterTotal VotesVote %Average Time (s)SuccessFailureSuccess Rate
{index + 1}{index + 1} {item.name} {item.skillParameter.toFixed(2)}{item.totalVotes}{item.votePercentage}{item.averageExecutionTime.toFixed(2)}{item.passCount}{item.failCount}{successRate}
+ + + + + + + + + + {filteredData.slice(0, 50).map((execution, index) => ( + + + + + + + ))} + +
TimestampAgentStatusOutput
{new Date(execution.timestamp).toLocaleString()}{execution.agentId ? execution.agentId.name : 'Unknown Agent'}{execution.isSuccess ? 'Success' : 'Error'}{execution.output}
+
+ + + + ); +}; + +export default MonitoringDashboard; diff --git a/agent-arena/client/src/components/RequestPasswordReset.js b/agent-arena/client/src/components/RequestPasswordReset.js new file mode 100644 index 0000000000..528061fa46 --- /dev/null +++ b/agent-arena/client/src/components/RequestPasswordReset.js @@ -0,0 +1,36 @@ +import React, { useState } from 'react'; +import axios from 'axios'; +import { Form, Button, Container } from 'react-bootstrap'; +import {toast } from 'react-toastify'; +import 'react-toastify/dist/ReactToastify.css'; + +const RequestPasswordReset = () => { + const [email, setEmail] = useState(''); + + const handleSubmit = async (e) => { + e.preventDefault(); + try { + await axios.post('https://agent-arena.vercel.app/api/auth/request-password-reset', { email }); + toast.success('Password reset link has been sent to your email'); + } catch (error) { + console.error('Error requesting password reset', error); + toast.error('An error occurred while requesting the password reset'); + } + }; + + return ( + +
+ + Email + setEmail(e.target.value)} /> + + +
+
+ ); +}; + +export default RequestPasswordReset; diff --git a/agent-arena/client/src/components/ResetPassword.js b/agent-arena/client/src/components/ResetPassword.js new file mode 100644 index 0000000000..69e9494555 --- /dev/null +++ b/agent-arena/client/src/components/ResetPassword.js @@ -0,0 +1,40 @@ +import React, { useState } from 'react'; +import axios from 'axios'; +import { useParams, useNavigate } from 'react-router-dom'; +import { Form, Button, Container } from 'react-bootstrap'; +import {toast } from 'react-toastify'; +import 'react-toastify/dist/ReactToastify.css'; + +const ResetPassword = () => { + const [password, setPassword] = useState(''); + const { token } = useParams(); + const navigate = useNavigate(); + + const handleSubmit = async (e) => { + e.preventDefault(); + try { + await axios.post(`https://agent-arena.vercel.app/api/auth/reset-password/${token}`, { password }); + toast.success('Password has been reset successfully'); + navigate('/'); // Redirects to the base URL after successful reset + } catch (error) { + console.error('Error resetting password', error); + toast.error('An error occurred while resetting your password'); + } + }; + + return ( + +
+ + New Password + setPassword(e.target.value)} /> + + +
+
+ ); +}; + +export default ResetPassword; diff --git a/agent-arena/client/src/components/StaticCodeEditor.js b/agent-arena/client/src/components/StaticCodeEditor.js index e49d20cfba..e16ce8313f 100644 --- a/agent-arena/client/src/components/StaticCodeEditor.js +++ b/agent-arena/client/src/components/StaticCodeEditor.js @@ -3,8 +3,14 @@ import AceEditor from 'react-ace'; import 'ace-builds/src-noconflict/mode-python'; import 'ace-builds/src-noconflict/theme-monokai'; import { Card } from 'react-bootstrap'; +import DOMPurify from 'dompurify'; const StaticCodeEditor = ({ executedCode, output }) => { + // Function to safely set HTML content + const createMarkup = (html) => { + return {__html: DOMPurify.sanitize(html)}; + } + return ( @@ -17,20 +23,29 @@ const StaticCodeEditor = ({ executedCode, output }) => { editorProps={{ $blockScrolling: true }} width="100%" height="300px" + fontSize="14px" + setOptions={{ + fontFamily: "'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', monospace", + }} + /> +
-        
-          {output}
-        
       
     
   );
 };
 
-export default StaticCodeEditor;
+export default StaticCodeEditor;
\ No newline at end of file
diff --git a/agent-arena/client/src/components/UserList.js b/agent-arena/client/src/components/UserList.js
index 5fe7b18de2..c38cbb79dc 100644
--- a/agent-arena/client/src/components/UserList.js
+++ b/agent-arena/client/src/components/UserList.js
@@ -1,26 +1,50 @@
 import React, { useState, useEffect, useContext } from 'react';
 import axios from 'axios';
-import { Card, Button, Container, Row, Col, Form } from 'react-bootstrap';
+import { Container, Row, Col, Card, Button, Form } from 'react-bootstrap';
 import { useNavigate } from 'react-router-dom';
 import Select from 'react-select';
-import { ThemeContext } from '../App'; // Import ThemeContext from App
+import { toast} from 'react-toastify';
+import { ThemeContext } from '../App';
+import { Analytics } from "@vercel/analytics/react"
+
 
 const UserList = () => {
   const [users, setUsers] = useState([]);
   const [filteredUsers, setFilteredUsers] = useState([]);
   const [searchQuery, setSearchQuery] = useState('');
-  const [sortOption, setSortOption] = useState('');
+  const [sortOption, setSortOption] = useState('savedPrompts'); // Default sort by saved prompts
   const navigate = useNavigate();
-  const { theme } = useContext(ThemeContext); // Get the current theme
+  const { theme } = useContext(ThemeContext);
 
+  
   useEffect(() => {
     const fetchUsers = async () => {
       try {
         const response = await axios.get('https://agent-arena.vercel.app/api/users', {
-          headers: { Authorization: `Bearer ${localStorage.getItem('token')}` }
+          headers: { Authorization: `Bearer ${localStorage.getItem('token')}` },
+        });
+
+        console.log(response.data);
+
+        // Sort users by saved prompts by default
+        let sortedUsers = response.data.sort((a, b) => {
+          const aLength = a.savedPrompts ? a.savedPrompts.length : 0;
+          const bLength = b.savedPrompts ? b.savedPrompts.length : 0;
+          return bLength - aLength;
         });
-        setUsers(response.data);
-        setFilteredUsers(response.data);
+        
+
+        // Ensure Nithik is placed in the third position only if the current third user has 0 saved prompts
+        const nithikIndex = sortedUsers.findIndex(user => user.name === 'Nithik');
+        const thirdUser = sortedUsers[2];
+
+        if (nithikIndex !== -1 && thirdUser && thirdUser.savedPrompts.length === 0) {
+          const [nithikUser] = sortedUsers.splice(nithikIndex, 1);
+          sortedUsers.splice(2, 0, nithikUser); // Insert Nithik at the third position if third user has 0 saved prompts
+        }
+
+        setUsers(sortedUsers);
+        setFilteredUsers(sortedUsers);
       } catch (error) {
         console.error('Error fetching users:', error);
       }
@@ -34,55 +58,40 @@ const UserList = () => {
   };
 
   const handleSearch = (e) => {
-    setSearchQuery(e.target.value);
     const query = e.target.value.toLowerCase();
-    setFilteredUsers(users.filter(user => 
-      user.name.toLowerCase().includes(query) || 
-      user.bio.toLowerCase().includes(query) || 
-      user.role.toLowerCase().includes(query)
-    ));
+    setSearchQuery(query);
+    setFilteredUsers(
+      users.filter(
+        (user) =>
+          user.name.toLowerCase().includes(query) ||
+          user.bio.toLowerCase().includes(query) ||
+          user.role.toLowerCase().includes(query)
+      )
+    );
   };
 
   const handleSortChange = (selectedOption) => {
     setSortOption(selectedOption.value);
-    let sortedUsers;
-    if (selectedOption.value === 'likes') {
-      sortedUsers = [...filteredUsers].sort((a, b) => b.totalLikes - a.totalLikes);
-    } else if (selectedOption.value === 'savedPrompts') {
-      sortedUsers = [...filteredUsers].sort((a, b) => b.savedPrompts.length - a.savedPrompts.length);
-    }
+    const sortedUsers = [...filteredUsers].sort((a, b) => {
+      if (selectedOption.value === 'likes') return b.totalLikes - a.totalLikes;
+      if (selectedOption.value === 'savedPrompts') return b.savedPrompts.length - a.savedPrompts.length;
+      return 0;
+    });
     setFilteredUsers(sortedUsers);
   };
 
+  const notifyLikesDislikes = () => {
+    toast.info('You must like a specific prompt by the user. Click "View Prompts" to do so.');
+  };
+
   const sortOptions = [
     { value: 'likes', label: 'Total Likes' },
     { value: 'savedPrompts', label: 'Saved Prompts' },
   ];
 
-  const customStyles = {
-    control: (base) => ({
-      ...base,
-      minHeight: 40,
-      fontSize: 14,
-      width: '100%',
-    }),
-    menu: (base) => ({
-      ...base,
-      fontSize: 14,
-    }),
-    singleValue: (base) => ({
-      ...base,
-      color: '#4b0082',
-    }),
-    option: (base, { isFocused }) => ({
-      ...base,
-      color: '#4b0082',
-      backgroundColor: isFocused ? '#d3d3d3' : 'white',
-    }),
-  };
-
   return (
     
+      
       

Users

Explore the users of the LLM Agent Arena platform. Click on "View Prompts" to see the prompts they've saved, @@ -95,7 +104,6 @@ const UserList = () => { placeholder="Search users..." value={searchQuery} onChange={handleSearch} - className="mb-4" /> @@ -103,28 +111,45 @@ const UserList = () => { options={sortOptions} onChange={handleSortChange} placeholder="Sort by..." - styles={customStyles} + defaultValue={sortOptions[1]} // Default sort by saved prompts /> - {filteredUsers.map(user => ( + {filteredUsers.map((user) => ( - + - {user.name} - {user.bio} - Role: {user.role} - Saved Prompts: {user.savedPrompts.length} + + {user.name} + + + {user.bio} + + + Role: {user.role} + + + Saved Prompts: {user.savedPrompts.length} +

- - + +
- +
diff --git a/agent-arena/client/src/components/UserProfile.js b/agent-arena/client/src/components/UserProfile.js index b41e5f84b5..71aba37ea6 100644 --- a/agent-arena/client/src/components/UserProfile.js +++ b/agent-arena/client/src/components/UserProfile.js @@ -1,9 +1,45 @@ import React, { useState, useEffect } from 'react'; import axios from 'axios'; -import { Form, Button, Container, Row, Col, Card } from 'react-bootstrap'; +import { Form, Button, Container, Row, Col, Card, Collapse } from 'react-bootstrap'; import { Link } from 'react-router-dom'; import CodeEditor from './CodeEditor'; import AgentDropdown from './AgentDropdown'; +import { toast } from 'react-toastify'; + +const apiKeysList = [ + "SERPER_API_KEY", + "OPENAI_API_KEY", + "COMPOSIO_API_KEY", + "ALPHAVANTAGE_API_KEY", + "BRAVESEARCH_API_KEY", + "EXA_API_KEY", + "ANTHROPIC_API_KEY", + "OPENWEATHERMAP_API_KEY", + "SERPAPI_API_KEY", + "ASKNEWS_CLIENT_ID", + "ASKNEWS_CLIENT_SECRET", + "TAVILY_API_KEY", + "EDENAI_API_KEY", + "E2B_API_KEY", + "RIZA_API_KEY", + "GOLDEN_API_KEY", + "WOLFRAM_APP_ID", + "WOLFRAM_ALPHA_APPID", + "YELP_CLIENT_ID", + "YELP_API_KEY", + "LANGCHAIN_API_KEY", + "GOOGLE_CLOUD_PROJECT_ID", + "GOOGLE_CLOUD_PRIVATE_KEY_ID", + "GOOGLE_CLOUD_PRIVATE_KEY", + "GOOGLE_CLOUD_CLIENT_EMAIL", + "GOOGLE_CLOUD_CLIENT_ID", + "GOOGLE_CLOUD_AUTH_URI", + "GOOGLE_CLOUD_TOKEN_URI", + "GOOGLE_CLOUD_AUTH_PROVIDER_CERT_URL", + "GOOGLE_CLOUD_CLIENT_CERT_URL", + "TOGETHER_API_KEY", + "MISTRAL_API_KEY", +]; const UserProfile = () => { const [profile, setProfile] = useState(null); @@ -17,8 +53,10 @@ const UserProfile = () => { name: '', email: '', bio: '', - role: '' + role: '', + apiKeys: {}, }); + const [apiKeysExpanded, setApiKeysExpanded] = useState(false); // New state for API keys collapse useEffect(() => { const fetchProfile = async () => { @@ -31,7 +69,8 @@ const UserProfile = () => { name: response.data.name, email: response.data.email, bio: response.data.bio, - role: response.data.role + role: response.data.role, + apiKeys: response.data.apiKeys || {}, // Ensure this exists }); } catch (error) { console.error('Error fetching profile:', error); @@ -108,7 +147,22 @@ const UserProfile = () => { }; const handleProfileChange = (e) => { - setEditProfile({ ...editProfile, [e.target.name]: e.target.value }); + const { name, value } = e.target; + setEditProfile(prevState => ({ + ...prevState, + [name]: value, + })); + }; + + const handleApiKeyChange = (e) => { + const { name, value } = e.target; + setEditProfile(prevState => ({ + ...prevState, + apiKeys: { + ...prevState.apiKeys, + [name]: value, + }, + })); }; const handleProfileSave = async () => { @@ -116,12 +170,27 @@ const UserProfile = () => { await axios.put('https://agent-arena.vercel.app/api/profile', editProfile, { headers: { Authorization: `Bearer ${localStorage.getItem('token')}` } }); - alert('Profile updated successfully'); + toast.success('Profile updated successfully'); } catch (error) { console.error('Error updating profile:', error); } }; + const handleAPIKeysSave = async () => { + try { + const token = localStorage.getItem('token'); + const response = await axios.put(`https://agent-arena.vercel.app/api/users/${profile._id}/api-keys`, { + apiKeys: editProfile.apiKeys + }, { + headers: { Authorization: `Bearer ${token}` } + }); + toast.success('API Keys updated successfully'); + setProfile(response.data); // Update local profile state with the latest data + } catch (error) { + console.error('Error updating API keys:', error); + } + }; + const handleLikePrompt = async (promptId) => { try { await axios.post('https://agent-arena.vercel.app/api/prompts/like', { promptId }, { @@ -185,6 +254,41 @@ const UserProfile = () => { +
+

API Keys

+

+ API keys are required for specific agents to function properly. You can add your own keys for better performance + and to avoid rate limits. Please ensure you enter the correct key for each API. +

+ + +
+ {apiKeysList.map(key => ( + + + + {key.replace(/_/g, ' ')} + + + + + ))} + +
+

Saved Prompts

@@ -225,4 +329,4 @@ const UserProfile = () => { ); }; -export default UserProfile; \ No newline at end of file +export default UserProfile; diff --git a/agent-arena/client/src/components/UserPrompts.js b/agent-arena/client/src/components/UserPrompts.js index 774fb405d2..acf920823b 100644 --- a/agent-arena/client/src/components/UserPrompts.js +++ b/agent-arena/client/src/components/UserPrompts.js @@ -19,63 +19,53 @@ const UserPrompts = () => { const [initialCode, setInitialCode] = useState(''); const [searchQuery, setSearchQuery] = useState(''); const [sortOption, setSortOption] = useState(''); + const [currentPage, setCurrentPage] = useState(1); + const [totalPages, setTotalPages] = useState(1); + + const fetchPrompts = async (page) => { + try { + const token = localStorage.getItem('token'); + const headers = token ? { Authorization: `Bearer ${token}` } : {}; + const response = await axios.get(`https://agent-arena.vercel.app/api/prompts/user/${userId}?page=${page}&limit=10`, { headers }); + + setPrompts(response.data.prompts); + setFilteredPrompts(response.data.prompts); + setTotalPages(response.data.totalPages); + } catch (error) { + console.error('Error fetching prompts:', error); + } + }; + + const fetchUserData = async () => { + try { + const token = localStorage.getItem('token'); + const headers = token ? { Authorization: `Bearer ${token}` } : {}; + const response = await axios.get(`https://agent-arena.vercel.app/api/users/${userId}`, { headers }); + setUser(response.data); // Fetch and set user data + } catch (error) { + console.error('Error fetching user data:', error); + } + }; + + const fetchAgents = async () => { + try { + const token = localStorage.getItem('token'); + const headers = token ? { Authorization: `Bearer ${token}` } : {}; + const response = await axios.get(`https://agent-arena.vercel.app/api/agents`, { headers }); + setAgents(response.data); // Fetch and set agents data + } catch (error) { + console.error('Error fetching agents:', error); + } + }; useEffect(() => { - const fetchUser = async () => { - try { - const token = localStorage.getItem('token'); - if (token) { - const response = await axios.get(`https://agent-arena.vercel.app/api/profile`, { - headers: { Authorization: `Bearer ${token}` } - }); - setCurrentUserId(response.data._id); - } - } catch (error) { - console.error('Error fetching user:', error); - } - }; - - const fetchPrompts = async () => { - try { - const token = localStorage.getItem('token'); - const headers = token ? { Authorization: `Bearer ${token}` } : {}; - const response = await axios.get(`https://agent-arena.vercel.app/api/prompts/user/${userId}`, { headers }); - setPrompts(response.data); - setFilteredPrompts(response.data); - } catch (error) { - console.error('Error fetching prompts:', error); - } - }; - - const fetchUserData = async () => { - try { - const token = localStorage.getItem('token'); - const headers = token ? { Authorization: `Bearer ${token}` } : {}; - const response = await axios.get(`https://agent-arena.vercel.app/api/users/${userId}`, { headers }); - setUser(response.data); - } catch (error) { - console.error('Error fetching user data:', error); - } - }; - - const fetchAgents = async () => { - try { - const token = localStorage.getItem('token'); - const headers = token ? { Authorization: `Bearer ${token}` } : {}; - const response = await axios.get(`https://agent-arena.vercel.app/api/agents`, { headers }); - setAgents(response.data); - } catch (error) { - console.error('Error fetching agents:', error); - } - }; - - fetchUser(); - fetchPrompts(); + fetchPrompts(currentPage); fetchUserData(); - fetchAgents(); - }, [userId]); + fetchAgents(); // Fetch agents data on load + }, [userId, currentPage]); useEffect(() => { + // If an agent is selected, filter the prompts based on the selected agent if (selectedAgent) { const agentPrompts = prompts.filter(prompt => (prompt.leftAgent && prompt.leftAgent._id === selectedAgent._id) || @@ -85,12 +75,13 @@ const UserPrompts = () => { setSelectedAgentPrompts(agentPrompts); setInitialCode(selectedAgent.code || ''); } else { + // If no agent is selected, show all prompts setSelectedAgentPrompts(filteredPrompts); } }, [selectedAgent, filteredPrompts]); const handleLike = async (promptId) => { - if (!currentUserId) { + if (currentUserId) { toast.error('You need to be logged in to like prompts'); return; } @@ -100,11 +91,7 @@ const UserPrompts = () => { await axios.post('https://agent-arena.vercel.app/api/prompts/like', { promptId }, { headers: { Authorization: `Bearer ${token}` } }); - const response = await axios.get(`https://agent-arena.vercel.app/api/prompts/user/${userId}`, { - headers: { Authorization: `Bearer ${token}` } - }); - setPrompts(response.data); - setFilteredPrompts(response.data); + fetchPrompts(currentPage); } catch (error) { console.error('Error liking prompt:', error); } @@ -112,7 +99,7 @@ const UserPrompts = () => { const handleDislike = async (promptId) => { if (!currentUserId) { - alert("You need to be logged in to dislike prompts."); + toast.error("You need to be logged in to dislike prompts."); return; } @@ -121,11 +108,7 @@ const UserPrompts = () => { await axios.post('https://agent-arena.vercel.app/api/prompts/dislike', { promptId }, { headers: { Authorization: `Bearer ${token}` } }); - const response = await axios.get(`https://agent-arena.vercel.app/api/prompts/user/${userId}`, { - headers: { Authorization: `Bearer ${token}` } - }); - setPrompts(response.data); - setFilteredPrompts(response.data); + fetchPrompts(currentPage); } catch (error) { console.error('Error disliking prompt:', error); } @@ -179,9 +162,9 @@ const UserPrompts = () => { return ( -

{user.name}'s Prompts

-

{user.bio}

-

Role: {user.role}

+

{user?.name || "User's"} Prompts

+

{user?.bio || "No bio available"}

+

Role: {user?.role || "No role available"}

{ - {selectedAgentPrompts.map(prompt => ( - - - -

{prompt.text}

- - -
-
- - ))} + {selectedAgent + ? selectedAgentPrompts.map(prompt => ( + + + +

{prompt.text}

+ + +
+
+ + )) + : filteredPrompts.map(prompt => ( + + + +

{prompt.text}

+ + +
+
+ + ))} {selectedAgent && ( {}} /> )} +
+ + Page {currentPage} of {totalPages} + +
+
); };