autogen scenarios

This commit is contained in:
Kyle Corbitt
2023-06-27 13:00:23 -07:00
parent ab32995eb9
commit 0a675cd7f7
8 changed files with 472 additions and 50 deletions

View File

@@ -30,14 +30,17 @@
"dayjs": "^1.11.8", "dayjs": "^1.11.8",
"dotenv": "^16.3.1", "dotenv": "^16.3.1",
"framer-motion": "^10.12.17", "framer-motion": "^10.12.17",
"json-stringify-pretty-compact": "^4.0.0",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"next": "^13.4.2", "next": "^13.4.2",
"next-auth": "^4.22.1", "next-auth": "^4.22.1",
"nextjs-routes": "^2.0.1", "nextjs-routes": "^2.0.1",
"openai": "^3.3.0",
"posthog-js": "^1.68.4", "posthog-js": "^1.68.4",
"react": "18.2.0", "react": "18.2.0",
"react-dom": "18.2.0", "react-dom": "18.2.0",
"react-icons": "^4.10.1", "react-icons": "^4.10.1",
"react-syntax-highlighter": "^15.5.0",
"react-textarea-autosize": "^8.5.0", "react-textarea-autosize": "^8.5.0",
"superjson": "1.12.2", "superjson": "1.12.2",
"tsx": "^3.12.7", "tsx": "^3.12.7",
@@ -50,6 +53,7 @@
"@types/node": "^18.16.0", "@types/node": "^18.16.0",
"@types/react": "^18.2.6", "@types/react": "^18.2.6",
"@types/react-dom": "^18.2.4", "@types/react-dom": "^18.2.4",
"@types/react-syntax-highlighter": "^15.5.7",
"@typescript-eslint/eslint-plugin": "^5.59.6", "@typescript-eslint/eslint-plugin": "^5.59.6",
"@typescript-eslint/parser": "^5.59.6", "@typescript-eslint/parser": "^5.59.6",
"eslint": "^8.40.0", "eslint": "^8.40.0",

224
pnpm-lock.yaml generated
View File

@@ -59,6 +59,9 @@ dependencies:
framer-motion: framer-motion:
specifier: ^10.12.17 specifier: ^10.12.17
version: 10.12.17(react-dom@18.2.0)(react@18.2.0) version: 10.12.17(react-dom@18.2.0)(react@18.2.0)
json-stringify-pretty-compact:
specifier: ^4.0.0
version: 4.0.0
lodash: lodash:
specifier: ^4.17.21 specifier: ^4.17.21
version: 4.17.21 version: 4.17.21
@@ -71,6 +74,9 @@ dependencies:
nextjs-routes: nextjs-routes:
specifier: ^2.0.1 specifier: ^2.0.1
version: 2.0.1(next@13.4.2) version: 2.0.1(next@13.4.2)
openai:
specifier: ^3.3.0
version: 3.3.0
posthog-js: posthog-js:
specifier: ^1.68.4 specifier: ^1.68.4
version: 1.68.4 version: 1.68.4
@@ -83,6 +89,9 @@ dependencies:
react-icons: react-icons:
specifier: ^4.10.1 specifier: ^4.10.1
version: 4.10.1(react@18.2.0) version: 4.10.1(react@18.2.0)
react-syntax-highlighter:
specifier: ^15.5.0
version: 15.5.0(react@18.2.0)
react-textarea-autosize: react-textarea-autosize:
specifier: ^8.5.0 specifier: ^8.5.0
version: 8.5.0(@types/react@18.2.6)(react@18.2.0) version: 8.5.0(@types/react@18.2.6)(react@18.2.0)
@@ -115,6 +124,9 @@ devDependencies:
'@types/react-dom': '@types/react-dom':
specifier: ^18.2.4 specifier: ^18.2.4
version: 18.2.4 version: 18.2.4
'@types/react-syntax-highlighter':
specifier: ^15.5.7
version: 15.5.7
'@typescript-eslint/eslint-plugin': '@typescript-eslint/eslint-plugin':
specifier: ^5.59.6 specifier: ^5.59.6
version: 5.59.6(@typescript-eslint/parser@5.59.6)(eslint@8.40.0)(typescript@5.0.4) version: 5.59.6(@typescript-eslint/parser@5.59.6)(eslint@8.40.0)(typescript@5.0.4)
@@ -2033,6 +2045,12 @@ packages:
resolution: {integrity: sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==} resolution: {integrity: sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==}
dev: true dev: true
/@types/hast@2.3.4:
resolution: {integrity: sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==}
dependencies:
'@types/unist': 2.0.6
dev: false
/@types/json-schema@7.0.12: /@types/json-schema@7.0.12:
resolution: {integrity: sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==} resolution: {integrity: sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==}
dev: true dev: true
@@ -2071,6 +2089,12 @@ packages:
'@types/react': 18.2.6 '@types/react': 18.2.6
dev: true dev: true
/@types/react-syntax-highlighter@15.5.7:
resolution: {integrity: sha512-bo5fEO5toQeyCp0zVHBeggclqf5SQ/Z5blfFmjwO5dkMVGPgmiwZsJh9nu/Bo5L7IHTuGWrja6LxJVE2uB5ZrQ==}
dependencies:
'@types/react': 18.2.6
dev: true
/@types/react@18.2.6: /@types/react@18.2.6:
resolution: {integrity: sha512-wRZClXn//zxCFW+ye/D2qY65UsYP1Fpex2YXorHc8awoNamkMZSvBxwxdYVInsHOZZd2Ppq8isnSzJL5Mpf8OA==} resolution: {integrity: sha512-wRZClXn//zxCFW+ye/D2qY65UsYP1Fpex2YXorHc8awoNamkMZSvBxwxdYVInsHOZZd2Ppq8isnSzJL5Mpf8OA==}
dependencies: dependencies:
@@ -2085,6 +2109,10 @@ packages:
resolution: {integrity: sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==} resolution: {integrity: sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==}
dev: true dev: true
/@types/unist@2.0.6:
resolution: {integrity: sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==}
dev: false
/@typescript-eslint/eslint-plugin@5.59.6(@typescript-eslint/parser@5.59.6)(eslint@8.40.0)(typescript@5.0.4): /@typescript-eslint/eslint-plugin@5.59.6(@typescript-eslint/parser@5.59.6)(eslint@8.40.0)(typescript@5.0.4):
resolution: {integrity: sha512-sXtOgJNEuRU5RLwPUb1jxtToZbgvq3M6FPpY4QENxoOggK+UpTxUBpj6tD8+Qh2g46Pi9We87E+eHnUw8YcGsw==} resolution: {integrity: sha512-sXtOgJNEuRU5RLwPUb1jxtToZbgvq3M6FPpY4QENxoOggK+UpTxUBpj6tD8+Qh2g46Pi9We87E+eHnUw8YcGsw==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -2347,6 +2375,10 @@ packages:
resolution: {integrity: sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==} resolution: {integrity: sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==}
dev: true dev: true
/asynckit@0.4.0:
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
dev: false
/available-typed-arrays@1.0.5: /available-typed-arrays@1.0.5:
resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
@@ -2357,6 +2389,14 @@ packages:
engines: {node: '>=4'} engines: {node: '>=4'}
dev: true dev: true
/axios@0.26.1:
resolution: {integrity: sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==}
dependencies:
follow-redirects: 1.15.2
transitivePeerDependencies:
- debug
dev: false
/axobject-query@3.2.1: /axobject-query@3.2.1:
resolution: {integrity: sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==} resolution: {integrity: sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==}
dependencies: dependencies:
@@ -2459,6 +2499,18 @@ packages:
supports-color: 7.2.0 supports-color: 7.2.0
dev: true dev: true
/character-entities-legacy@1.1.4:
resolution: {integrity: sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==}
dev: false
/character-entities@1.2.4:
resolution: {integrity: sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==}
dev: false
/character-reference-invalid@1.1.4:
resolution: {integrity: sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==}
dev: false
/chokidar@3.5.3: /chokidar@3.5.3:
resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
engines: {node: '>= 8.10.0'} engines: {node: '>= 8.10.0'}
@@ -2503,6 +2555,17 @@ packages:
resolution: {integrity: sha512-kJhwH5nAwb34tmyuqq/lgjEKzlFXn1U99NlnB6Ws4qVaERcRUYeYP1cBw6BJ4vxaWStAUEef4WMr7WjOCnBt8w==} resolution: {integrity: sha512-kJhwH5nAwb34tmyuqq/lgjEKzlFXn1U99NlnB6Ws4qVaERcRUYeYP1cBw6BJ4vxaWStAUEef4WMr7WjOCnBt8w==}
dev: false dev: false
/combined-stream@1.0.8:
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
engines: {node: '>= 0.8'}
dependencies:
delayed-stream: 1.0.0
dev: false
/comma-separated-tokens@1.0.8:
resolution: {integrity: sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==}
dev: false
/compute-scroll-into-view@1.0.20: /compute-scroll-into-view@1.0.20:
resolution: {integrity: sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==} resolution: {integrity: sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==}
dev: false dev: false
@@ -2632,6 +2695,11 @@ packages:
object-keys: 1.1.1 object-keys: 1.1.1
dev: true dev: true
/delayed-stream@1.0.0:
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
engines: {node: '>=0.4.0'}
dev: false
/dequal@2.0.3: /dequal@2.0.3:
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
engines: {node: '>=6'} engines: {node: '>=6'}
@@ -3161,6 +3229,12 @@ packages:
reusify: 1.0.4 reusify: 1.0.4
dev: true dev: true
/fault@1.0.4:
resolution: {integrity: sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==}
dependencies:
format: 0.2.2
dev: false
/fflate@0.4.8: /fflate@0.4.8:
resolution: {integrity: sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==} resolution: {integrity: sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==}
dev: false dev: false
@@ -3209,12 +3283,36 @@ packages:
tslib: 2.5.3 tslib: 2.5.3
dev: false dev: false
/follow-redirects@1.15.2:
resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==}
engines: {node: '>=4.0'}
peerDependencies:
debug: '*'
peerDependenciesMeta:
debug:
optional: true
dev: false
/for-each@0.3.3: /for-each@0.3.3:
resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==}
dependencies: dependencies:
is-callable: 1.2.7 is-callable: 1.2.7
dev: true dev: true
/form-data@4.0.0:
resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
engines: {node: '>= 6'}
dependencies:
asynckit: 0.4.0
combined-stream: 1.0.8
mime-types: 2.1.35
dev: false
/format@0.2.2:
resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==}
engines: {node: '>=0.4.x'}
dev: false
/framer-motion@10.12.17(react-dom@18.2.0)(react@18.2.0): /framer-motion@10.12.17(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-IR+aAYntsyu6ofyxqQV4QYotmOqzcuKxhqNpfc3DXJjNWOPpOeSyH0A+In3IEBu49Yx/+PNht+YMeZSdCNaYbw==} resolution: {integrity: sha512-IR+aAYntsyu6ofyxqQV4QYotmOqzcuKxhqNpfc3DXJjNWOPpOeSyH0A+In3IEBu49Yx/+PNht+YMeZSdCNaYbw==}
peerDependencies: peerDependencies:
@@ -3437,6 +3535,24 @@ packages:
dependencies: dependencies:
function-bind: 1.1.1 function-bind: 1.1.1
/hast-util-parse-selector@2.2.5:
resolution: {integrity: sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==}
dev: false
/hastscript@6.0.0:
resolution: {integrity: sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==}
dependencies:
'@types/hast': 2.3.4
comma-separated-tokens: 1.0.8
hast-util-parse-selector: 2.2.5
property-information: 5.6.0
space-separated-tokens: 1.1.5
dev: false
/highlight.js@10.7.3:
resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==}
dev: false
/hoist-non-react-statics@3.3.2: /hoist-non-react-statics@3.3.2:
resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==}
dependencies: dependencies:
@@ -3506,6 +3622,17 @@ packages:
loose-envify: 1.4.0 loose-envify: 1.4.0
dev: false dev: false
/is-alphabetical@1.0.4:
resolution: {integrity: sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==}
dev: false
/is-alphanumerical@1.0.4:
resolution: {integrity: sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==}
dependencies:
is-alphabetical: 1.0.4
is-decimal: 1.0.4
dev: false
/is-array-buffer@3.0.2: /is-array-buffer@3.0.2:
resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==}
dependencies: dependencies:
@@ -3556,6 +3683,10 @@ packages:
has-tostringtag: 1.0.0 has-tostringtag: 1.0.0
dev: true dev: true
/is-decimal@1.0.4:
resolution: {integrity: sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==}
dev: false
/is-docker@2.2.1: /is-docker@2.2.1:
resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==}
engines: {node: '>=8'} engines: {node: '>=8'}
@@ -3578,6 +3709,10 @@ packages:
dependencies: dependencies:
is-extglob: 2.1.1 is-extglob: 2.1.1
/is-hexadecimal@1.0.4:
resolution: {integrity: sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==}
dev: false
/is-inside-container@1.0.0: /is-inside-container@1.0.0:
resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==}
engines: {node: '>=14.16'} engines: {node: '>=14.16'}
@@ -3716,6 +3851,10 @@ packages:
resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
dev: true dev: true
/json-stringify-pretty-compact@4.0.0:
resolution: {integrity: sha512-3CNZ2DnrpByG9Nqj6Xo8vqbjT4F6N+tb4Gb28ESAZjYZ5yqvmc56J+/kuIwkaAMOyblTQhUW7PxMkUb8Q36N3Q==}
dev: false
/json5@1.0.2: /json5@1.0.2:
resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==}
hasBin: true hasBin: true
@@ -3778,6 +3917,13 @@ packages:
dependencies: dependencies:
js-tokens: 4.0.0 js-tokens: 4.0.0
/lowlight@1.20.0:
resolution: {integrity: sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw==}
dependencies:
fault: 1.0.4
highlight.js: 10.7.3
dev: false
/lru-cache@6.0.0: /lru-cache@6.0.0:
resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
engines: {node: '>=10'} engines: {node: '>=10'}
@@ -3801,6 +3947,18 @@ packages:
picomatch: 2.3.1 picomatch: 2.3.1
dev: true dev: true
/mime-db@1.52.0:
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
engines: {node: '>= 0.6'}
dev: false
/mime-types@2.1.35:
resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
engines: {node: '>= 0.6'}
dependencies:
mime-db: 1.52.0
dev: false
/mime@3.0.0: /mime@3.0.0:
resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==}
engines: {node: '>=10.0.0'} engines: {node: '>=10.0.0'}
@@ -4063,6 +4221,15 @@ packages:
is-wsl: 2.2.0 is-wsl: 2.2.0
dev: true dev: true
/openai@3.3.0:
resolution: {integrity: sha512-uqxI/Au+aPRnsaQRe8CojU0eCR7I0mBiKjD3sNMzY6DaC1ZVrc85u98mtJW6voDug8fgGN+DIZmTDxTthxb7dQ==}
dependencies:
axios: 0.26.1
form-data: 4.0.0
transitivePeerDependencies:
- debug
dev: false
/openapi-typescript@5.4.1: /openapi-typescript@5.4.1:
resolution: {integrity: sha512-AGB2QiZPz4rE7zIwV3dRHtoUC/CWHhUjuzGXvtmMQN2AFV8xCTLKcZUHLcdPQmt/83i22nRE7+TxXOXkK+gf4Q==} resolution: {integrity: sha512-AGB2QiZPz4rE7zIwV3dRHtoUC/CWHhUjuzGXvtmMQN2AFV8xCTLKcZUHLcdPQmt/83i22nRE7+TxXOXkK+gf4Q==}
engines: {node: '>= 14.0.0'} engines: {node: '>= 14.0.0'}
@@ -4117,6 +4284,17 @@ packages:
dependencies: dependencies:
callsites: 3.1.0 callsites: 3.1.0
/parse-entities@2.0.0:
resolution: {integrity: sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==}
dependencies:
character-entities: 1.2.4
character-entities-legacy: 1.1.4
character-reference-invalid: 1.1.4
is-alphanumerical: 1.0.4
is-decimal: 1.0.4
is-hexadecimal: 1.0.4
dev: false
/parse-json@5.2.0: /parse-json@5.2.0:
resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
engines: {node: '>=8'} engines: {node: '>=8'}
@@ -4212,6 +4390,16 @@ packages:
dependencies: dependencies:
'@prisma/engines': 4.14.0 '@prisma/engines': 4.14.0
/prismjs@1.27.0:
resolution: {integrity: sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==}
engines: {node: '>=6'}
dev: false
/prismjs@1.29.0:
resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==}
engines: {node: '>=6'}
dev: false
/process-nextick-args@2.0.1: /process-nextick-args@2.0.1:
resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
dev: false dev: false
@@ -4223,6 +4411,12 @@ packages:
object-assign: 4.1.1 object-assign: 4.1.1
react-is: 16.13.1 react-is: 16.13.1
/property-information@5.6.0:
resolution: {integrity: sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==}
dependencies:
xtend: 4.0.2
dev: false
/punycode@2.3.0: /punycode@2.3.0:
resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==}
engines: {node: '>=6'} engines: {node: '>=6'}
@@ -4345,6 +4539,19 @@ packages:
tslib: 2.5.3 tslib: 2.5.3
dev: false dev: false
/react-syntax-highlighter@15.5.0(react@18.2.0):
resolution: {integrity: sha512-+zq2myprEnQmH5yw6Gqc8lD55QHnpKaU8TOcFeC/Lg/MQSs8UknEA0JC4nTZGFAXC2J2Hyj/ijJ7NlabyPi2gg==}
peerDependencies:
react: '>= 0.14.0'
dependencies:
'@babel/runtime': 7.22.5
highlight.js: 10.7.3
lowlight: 1.20.0
prismjs: 1.29.0
react: 18.2.0
refractor: 3.6.0
dev: false
/react-textarea-autosize@8.5.0(@types/react@18.2.6)(react@18.2.0): /react-textarea-autosize@8.5.0(@types/react@18.2.6)(react@18.2.0):
resolution: {integrity: sha512-cp488su3U9RygmHmGpJp0KEt0i/+57KCK33XVPH+50swVRBhIZYh0fGduz2YLKXwl9vSKBZ9HUXcg9PQXUXqIw==} resolution: {integrity: sha512-cp488su3U9RygmHmGpJp0KEt0i/+57KCK33XVPH+50swVRBhIZYh0fGduz2YLKXwl9vSKBZ9HUXcg9PQXUXqIw==}
engines: {node: '>=10'} engines: {node: '>=10'}
@@ -4394,6 +4601,14 @@ packages:
picomatch: 2.3.1 picomatch: 2.3.1
dev: false dev: false
/refractor@3.6.0:
resolution: {integrity: sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA==}
dependencies:
hastscript: 6.0.0
parse-entities: 2.0.0
prismjs: 1.27.0
dev: false
/regenerator-runtime@0.13.11: /regenerator-runtime@0.13.11:
resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==}
@@ -4542,6 +4757,10 @@ packages:
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
dev: false dev: false
/space-separated-tokens@1.1.5:
resolution: {integrity: sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==}
dev: false
/state-local@1.0.7: /state-local@1.0.7:
resolution: {integrity: sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==} resolution: {integrity: sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==}
dev: false dev: false
@@ -4952,6 +5171,11 @@ packages:
object-keys: 0.4.0 object-keys: 0.4.0
dev: false dev: false
/xtend@4.0.2:
resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
engines: {node: '>=0.4'}
dev: false
/yallist@4.0.0: /yallist@4.0.0:
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}

View File

@@ -1,12 +1,27 @@
import { Button } from "@chakra-ui/react"; import { Button, type ButtonProps, Fade, HStack } from "@chakra-ui/react";
import { useState } from "react";
import { BsPlus } from "react-icons/bs"; import { BsPlus } from "react-icons/bs";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
import { useExperiment, useHandledAsyncCallback } from "~/utils/hooks"; import { useExperiment, useHandledAsyncCallback } from "~/utils/hooks";
// Extracted Button styling into reusable component
const StyledButton = ({ children, onClick }: ButtonProps) => (
<Button
fontWeight="normal"
bgColor="transparent"
_hover={{ bgColor: "gray.100" }}
px={2}
onClick={onClick}
>
{children}
</Button>
);
export default function NewScenarioButton() { export default function NewScenarioButton() {
const experiment = useExperiment(); const experiment = useExperiment();
const mutation = api.scenarios.create.useMutation(); const mutation = api.scenarios.create.useMutation();
const utils = api.useContext(); const utils = api.useContext();
const [hovering, setHovering] = useState(false);
const [onClick] = useHandledAsyncCallback(async () => { const [onClick] = useHandledAsyncCallback(async () => {
if (!experiment.data) return; if (!experiment.data) return;
@@ -16,19 +31,31 @@ export default function NewScenarioButton() {
await utils.scenarios.list.invalidate(); await utils.scenarios.list.invalidate();
}, [mutation]); }, [mutation]);
const [onAutogenerate] = useHandledAsyncCallback(async () => {
if (!experiment.data) return;
await mutation.mutateAsync({
experimentId: experiment.data.id,
autogenerate: true,
});
await utils.scenarios.list.invalidate();
}, [mutation]);
return ( return (
<Button <HStack
w="100%" spacing={2}
alignItems="center" onMouseEnter={() => setHovering(true)}
justifyContent="flex-start" onMouseLeave={() => setHovering(false)}
fontWeight="normal"
bgColor="transparent"
_hover={{ bgColor: "gray.100" }}
px={2}
onClick={onClick}
> >
<StyledButton onClick={onClick}>
<BsPlus size={24} /> <BsPlus size={24} />
Add Scenario Add Scenario
</Button> </StyledButton>
<Fade in={hovering}>
<StyledButton onClick={onAutogenerate}>
<BsPlus size={24} />
Autogenerate Scenario
</StyledButton>
</Fade>
</HStack>
); );
} }

View File

@@ -1,14 +1,12 @@
import { api } from "~/utils/api"; import { api } from "~/utils/api";
import { type PromptVariant, type Scenario } from "./types"; import { type PromptVariant, type Scenario } from "./types";
import { Center, Spinner, Text } from "@chakra-ui/react"; import { Spinner, Text, Box } from "@chakra-ui/react";
import { useExperiment } from "~/utils/hooks"; import { useExperiment } from "~/utils/hooks";
import { cellPadding } from "../constants"; import { type CreateChatCompletionResponse } from "openai";
import SyntaxHighlighter from "react-syntax-highlighter";
const CellShell = ({ children }: { children: React.ReactNode }) => ( import { docco } from "react-syntax-highlighter/dist/cjs/styles/hljs";
<Center h="100%" w="100%" px={cellPadding.x} py={cellPadding.y}> import stringify from "json-stringify-pretty-compact";
{children} import { type ReactElement } from "react";
</Center>
);
export default function OutputCell({ export default function OutputCell({
scenario, scenario,
@@ -16,7 +14,7 @@ export default function OutputCell({
}: { }: {
scenario: Scenario; scenario: Scenario;
variant: PromptVariant; variant: PromptVariant;
}) { }): ReactElement | null {
const experiment = useExperiment(); const experiment = useExperiment();
const vars = api.templateVars.list.useQuery({ experimentId: experiment.data?.id ?? "" }).data; const vars = api.templateVars.list.useQuery({ experimentId: experiment.data?.id ?? "" }).data;
@@ -41,37 +39,34 @@ export default function OutputCell({
if (!vars) return null; if (!vars) return null;
if (disabledReason) if (disabledReason) return <Text color="gray.500">{disabledReason}</Text>;
return (
<CellShell>
<Text color="gray.500">{disabledReason}</Text>
</CellShell>
);
if (output.isLoading) if (output.isLoading) return <Spinner />;
return (
<CellShell>
<Spinner />
</CellShell>
);
if (!output.data) if (!output.data) return <Text color="gray.500">Error retrieving output</Text>;
return (
<CellShell>
<Text color="gray.500">Error retrieving output</Text>
</CellShell>
);
if (output.data.errorMessage) { if (output.data.errorMessage) {
return <Text color="red.600">Error: {output.data.errorMessage}</Text>;
}
const response = output.data?.output as unknown as CreateChatCompletionResponse;
const message = response?.choices?.[0]?.message;
if (message?.function_call) {
return ( return (
<CellShell> <Box fontSize="xs">
<Text color="red.600">Error: {output.data.errorMessage}</Text> <SyntaxHighlighter language="json" style={docco}>
</CellShell> {stringify(
{
function: message.function_call.name,
args: JSON.parse(message.function_call.arguments ?? "null"),
},
{ maxLength: 40 }
)}
</SyntaxHighlighter>
</Box>
); );
} }
return ( return <Box>{message?.content ?? JSON.stringify(output.data.output)}</Box>;
// @ts-expect-error TODO proper typing and error checks
<CellShell>{output.data.output.choices[0].message.content}</CellShell>
);
} }

View File

@@ -1,4 +1,4 @@
import { Grid, GridItem, type SystemStyleObject } from "@chakra-ui/react"; import { Center, Grid, GridItem, type SystemStyleObject } from "@chakra-ui/react";
import React, { useState } from "react"; import React, { useState } from "react";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
import NewScenarioButton from "./NewScenarioButton"; import NewScenarioButton from "./NewScenarioButton";
@@ -9,6 +9,7 @@ import VariantConfigEditor from "./VariantConfigEditor";
import VariantHeader from "./VariantHeader"; import VariantHeader from "./VariantHeader";
import type { Scenario, PromptVariant } from "./types"; import type { Scenario, PromptVariant } from "./types";
import ScenarioHeader from "~/server/ScenarioHeader"; import ScenarioHeader from "~/server/ScenarioHeader";
import { cellPadding } from "../constants";
const stickyHeaderStyle: SystemStyleObject = { const stickyHeaderStyle: SystemStyleObject = {
position: "sticky", position: "sticky",
@@ -41,7 +42,9 @@ const ScenarioRow = (props: { scenario: Scenario; variants: PromptVariant[] }) =
onMouseLeave={() => setIsHovered(false)} onMouseLeave={() => setIsHovered(false)}
sx={isHovered ? highlightStyle : undefined} sx={isHovered ? highlightStyle : undefined}
> >
<Center h="100%" w="100%" px={cellPadding.x} py={cellPadding.y}>
<OutputCell key={variant.id} scenario={props.scenario} variant={variant} /> <OutputCell key={variant.id} scenario={props.scenario} variant={variant} />
</Center>
</GridItem> </GridItem>
))} ))}
</React.Fragment> </React.Fragment>

157
src/server/api/autogen.ts Normal file
View File

@@ -0,0 +1,157 @@
import { type CreateChatCompletionRequest } from "openai";
import { prisma } from "../db";
import { openai } from "../utils/openai";
import { pick } from "lodash";
function promptHasVariable(prompt: string, variableName: string) {
return prompt.includes(`{{${variableName}}}`);
}
type AxiosError = {
response?: {
data?: {
error?: {
message?: string;
};
};
};
};
function isAxiosError(error: unknown): error is AxiosError {
if (typeof error === "object" && error !== null) {
// Initial check
const err = error as AxiosError;
return err.response?.data?.error?.message !== undefined; // Check structure
}
return false;
}
export const autogenerateScenarioValues = async (
experimentId: string
): Promise<Record<string, string>> => {
const [experiment, variables, existingScenarios, prompt] = await Promise.all([
prisma.experiment.findUnique({
where: {
id: experimentId,
},
}),
prisma.templateVariable.findMany({
where: {
experimentId,
},
}),
prisma.testScenario.findMany({
where: {
experimentId,
visible: true,
},
orderBy: {
sortIndex: "asc",
},
take: 10,
}),
prisma.promptVariant.findFirst({
where: {
experimentId,
visible: true,
},
orderBy: {
sortIndex: "asc",
},
}),
]);
if (!experiment || !(variables?.length > 0) || !prompt) return {};
const messages: CreateChatCompletionRequest["messages"] = [
{
role: "system",
content:
"The user is testing multiple scenarios against the same prompt. Attempt to generate a new scenario that is different from the others.",
},
];
const promptText = JSON.stringify(prompt.config);
if (variables.some((variable) => promptHasVariable(promptText, variable.label))) {
messages.push({
role: "user",
content: `Prompt template:\n---\n${promptText}`,
});
}
existingScenarios
.map(
(scenario) =>
pick(
scenario.variableValues,
variables.map((variable) => variable.label)
) as Record<string, string>
)
.filter((vals) => Object.keys(vals ?? {}).length > 0)
.forEach((vals) => {
messages.push({
role: "assistant",
// @ts-expect-error the openai type definition is wrong, the content field is required
content: null,
function_call: {
name: "add_scenario",
arguments: JSON.stringify(vals),
},
});
});
const variableProperties = variables.reduce((acc, variable) => {
acc[variable.label] = { type: "string" };
return acc;
}, {} as Record<string, { type: "string" }>);
console.log({
model: "gpt-3.5-turbo-0613",
messages,
functions: [
{
name: "add_scenario",
parameters: {
type: "object",
properties: variableProperties,
},
},
],
function_call: { name: "add_scenario" },
temperature: 0.5,
});
try {
const completion = await openai.createChatCompletion({
model: "gpt-3.5-turbo-0613",
messages,
functions: [
{
name: "add_scenario",
parameters: {
type: "object",
properties: variableProperties,
},
},
],
function_call: { name: "add_scenario" },
temperature: 0.5,
});
const parsed = JSON.parse(
completion.data.choices[0]?.message?.function_call?.arguments ?? "{}"
) as Record<string, string>;
return parsed;
} catch (e) {
// If it's an axios error, try to get the error message
if (isAxiosError(e)) {
console.error(e?.response?.data?.error?.message);
} else {
console.error(e);
}
return {};
}
return {};
};

View File

@@ -1,6 +1,7 @@
import { z } from "zod"; import { z } from "zod";
import { createTRPCRouter, publicProcedure } from "~/server/api/trpc"; import { createTRPCRouter, publicProcedure } from "~/server/api/trpc";
import { prisma } from "~/server/db"; import { prisma } from "~/server/db";
import { autogenerateScenarioValues } from "../autogen";
export const scenariosRouter = createTRPCRouter({ export const scenariosRouter = createTRPCRouter({
list: publicProcedure.input(z.object({ experimentId: z.string() })).query(async ({ input }) => { list: publicProcedure.input(z.object({ experimentId: z.string() })).query(async ({ input }) => {
@@ -19,6 +20,7 @@ export const scenariosRouter = createTRPCRouter({
.input( .input(
z.object({ z.object({
experimentId: z.string(), experimentId: z.string(),
autogenerate: z.boolean().optional(),
}) })
) )
.mutation(async ({ input }) => { .mutation(async ({ input }) => {
@@ -38,7 +40,9 @@ export const scenariosRouter = createTRPCRouter({
data: { data: {
experimentId: input.experimentId, experimentId: input.experimentId,
sortIndex: maxSortIndex + 1, sortIndex: maxSortIndex + 1,
variableValues: {}, variableValues: input.autogenerate
? await autogenerateScenarioValues(input.experimentId)
: {},
}, },
}); });
}), }),

View File

@@ -0,0 +1,8 @@
import { Configuration, OpenAIApi } from "openai";
import { env } from "~/env.mjs";
const configuration = new Configuration({
apiKey: env.OPENAI_API_KEY,
});
export const openai = new OpenAIApi(configuration);