This commit is contained in:
Lucian Petri
2022-12-30 02:42:10 +02:00
45 changed files with 875 additions and 604 deletions
+1 -1
View File
@@ -60,4 +60,4 @@ repos:
types_or: [javascript, jsx, ts, tsx]
language: system
pass_filenames: false
entry: bash -c 'cd website && npm install && npm run lint'
entry: bash -c 'cd website && npm ci && npm run lint'
+16 -15
View File
@@ -4,6 +4,21 @@ Open Assistant is a project meant to give everyone access to a great chat based
We believe that by doing this we will create a revolution in innovation in language. In the same way that stable-diffusion helped the world make art and images in new ways we hope Open Assistant can help improve the world by improving language itself.
## Do you want to try it out?
If you are interested in taking a look at the current state of the project, You can set up an entire stack needed to run **Open-Assistant**, including the
website, backend, and associated dependent services.
To start the demo, Run this in the root directory of the repository:
```sh
docker compose up --build
```
Then, navigate to `http://localhost:3000` (It may take some time to boot up) and interact with the website.
**Note:** When logging in via email, navigate to `http://localhost:1080` to get the magic email login link.
## The Plan
We want to get to an initial MVP as fast as possible, by following the 3-steps outlined in the InstructGPT paper.
@@ -82,7 +97,7 @@ addressed now, or filing an issue to handle it later.
Work is organized in the [project board](https://github.com/orgs/LAION-AI/projects/3).
**Anything that is in the `Todo` column and not assigned, is up for grabs. Meaning we'd be happy if anyone did those tasks.**
**Anything that is in the `Todo` column and not assigned, is up for grabs. Meaning we'd be happy for anyone to do these tasks.**
If you want to work on something, assign yourself to it or write a comment that you want to work on it and what you plan to do.
@@ -95,20 +110,6 @@ We are using Python 3.10 for the backend.
Check out the [High-Level Protocol Architecture](https://www.notion.so/High-Level-Protocol-Architecture-6f1fd3551da74213b560ead369f132dc)
## End to End Demo
If you are interested in just taking a look at the project.
You can set up an entire stack needed to run Open Assistant, including the
website, backend, and associated dependent services.
To start the demo, run this, in root directory:
```sh
docker compose up --build
```
Then, navigate to `http://localhost:3000` and interact with the website.
### Website
The website is built using Next.js and is in the `website` folder.
+3
View File
@@ -45,6 +45,7 @@
name: oasst-backend
image: ghcr.io/laion-ai/open-assistant/oasst-backend
state: started
recreate: true
pull: true
restart_policy: always
network_mode: oasst
@@ -61,6 +62,7 @@
name: oasst-web
image: ghcr.io/laion-ai/open-assistant/oasst-web
state: started
recreate: true
pull: true
restart_policy: always
network_mode: oasst
@@ -73,6 +75,7 @@
EMAIL_SERVER_PORT: "25"
EMAIL_FROM: info@example.com
NEXTAUTH_URL: http://web.dev.open-assistant.io/
DEBUG_LOGIN: "true"
ports:
- 3000:3000
command: bash wait-for-postgres.sh node server.js
@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
"""Added lang column for ISO-639-1 codes
Revision ID: ef0b52902560
Revises: d24b37426857
Create Date: 2022-12-28 18:24:21.393973
"""
import sqlalchemy as sa
import sqlmodel
from alembic import op
# revision identifiers, used by Alembic.
revision = "ef0b52902560"
down_revision = "d24b37426857"
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column(
"post", sa.Column("lang", sqlmodel.sql.sqltypes.AutoString(length=200), nullable=False, default="en-US")
)
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column("post", "lang")
# ### end Alembic commands ###
@@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
"""add collective flag to task
Revision ID: 464ec4667aae
Revises: ef0b52902560
Create Date: 2022-12-29 21:03:06.841962
"""
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision = "464ec4667aae"
down_revision = "ef0b52902560"
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column(
"work_package", sa.Column("collective", sa.Boolean(), server_default=sa.text("false"), nullable=False)
)
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column("work_package", "collective")
# ### end Alembic commands ###
@@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
"""add field trusted api client
Revision ID: 73ce3675c1f5
Revises: 464ec4667aae
Create Date: 2022-12-30 01:09:06.446020
"""
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision = "73ce3675c1f5"
down_revision = "464ec4667aae"
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column("api_client", sa.Column("trusted", sa.Boolean(), server_default=sa.text("false"), nullable=False))
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column("api_client", "trusted")
# ### end Alembic commands ###
+1 -1
View File
@@ -87,7 +87,7 @@ if settings.DEBUG_USE_SEED_DATA:
user_post_id="6f1d0711",
parent_post_id=None,
text="Hi!",
role="uesr",
role="user",
),
DummyPost(
task_post_id="74c381d4",
+1 -1
View File
@@ -40,7 +40,7 @@ def get_dummy_api_client(db: Session) -> ApiClient:
if api_client is None:
token = token_hex(32)
logger.info(f"ANY_API_KEY missing, inserting api_key: {token}")
api_client = ApiClient(id=ANY_API_KEY_ID, api_key=token, description="ANY_API_KEY, random token")
api_client = ApiClient(id=ANY_API_KEY_ID, api_key=token, description="ANY_API_KEY, random token", trusted=True)
db.add(api_client)
db.commit()
return api_client
+13 -1
View File
@@ -139,7 +139,7 @@ def request_task(
try:
pr = PromptRepository(db, api_client, request.user)
task, thread_id, parent_post_id = generate_task(request, pr)
pr.store_task(task, thread_id, parent_post_id)
pr.store_task(task, thread_id, parent_post_id, request.collective)
except OasstError:
raise
@@ -252,3 +252,15 @@ def post_interaction(
except Exception:
logger.exception("Interaction request failed.")
raise OasstError("Interaction request failed.", OasstErrorCode.TASK_INTERACTION_REQUEST_FAILED)
@router.post("/close")
def close_collective_task(
close_task_request: protocol_schema.TaskClose,
db: Session = Depends(deps.get_db),
api_key: APIKey = Depends(deps.get_api_key),
):
api_client = deps.api_auth(api_key, db)
pr = PromptRepository(db, api_client, user=None)
pr.close_task(close_task_request.post_id)
return protocol_schema.TaskDone()
+2
View File
@@ -34,12 +34,14 @@ class OasstErrorCode(IntEnum):
INVALID_TASK_TYPE = 2004
USER_NOT_SPECIFIED = 2005
NO_THREADS_FOUND = 2006
NO_REPLIES_FOUND = 2007
WORK_PACKAGE_NOT_FOUND = 2100
WORK_PACKAGE_EXPIRED = 2101
WORK_PACKAGE_PAYLOAD_TYPE_MISMATCH = 2102
WORK_PACKAGE_ALREADY_UPDATED = 2103
WORK_PACKAGE_NOT_ACK = 2104
WORK_PACKAGE_ALREADY_DONE = 2105
WORK_PACKAGE_NOT_COLLECTIVE = 2106
class OasstError(Exception):
@@ -4,6 +4,7 @@ from uuid import UUID, uuid4
import sqlalchemy as sa
import sqlalchemy.dialects.postgresql as pg
from sqlalchemy import false
from sqlmodel import Field, SQLModel
@@ -19,3 +20,4 @@ class ApiClient(SQLModel, table=True):
description: str = Field(max_length=256)
admin_email: Optional[str] = Field(max_length=256, nullable=True)
enabled: bool = Field(default=True)
trusted: bool = Field(sa_column=sa.Column(sa.Boolean, nullable=False, server_default=false()))
+1
View File
@@ -31,5 +31,6 @@ class Post(SQLModel, table=True):
)
payload_type: str = Field(nullable=False, max_length=200)
payload: PayloadContainer = Field(sa_column=sa.Column(payload_column_type(PayloadContainer), nullable=True))
lang: str = Field(nullable=False, max_length=200, default="en-US")
depth: int = Field(sa_column=sa.Column(sa.Integer, default=0, server_default=sa.text("0"), nullable=False))
children_count: int = Field(sa_column=sa.Column(sa.Integer, default=0, server_default=sa.text("0"), nullable=False))
@@ -32,6 +32,7 @@ class WorkPackage(SQLModel, table=True):
frontend_ref_post_id: Optional[str] = None
thread_id: Optional[UUID] = None
parent_post_id: Optional[UUID] = None
collective: bool = Field(sa_column=sa.Column(sa.Boolean, nullable=False, server_default=false()))
@property
def expired(self) -> bool:
+35 -10
View File
@@ -160,8 +160,9 @@ class PromptRepository:
payload=db_payload.PostPayload(text=text),
depth=depth,
)
wp.done = True
self.db.add(wp)
if not wp.collective:
wp.done = True
self.db.add(wp)
self.db.commit()
self.journal.log_text_reply(work_package=wp, post_id=new_post_id, role=role, length=len(text))
return user_post
@@ -186,6 +187,10 @@ class PromptRepository:
# store reaction to post
reaction_payload = db_payload.RatingReactionPayload(rating=rating.rating)
reaction = self.insert_reaction(post.id, reaction_payload)
if not work_package.collective:
work_package.done = True
self.db.add(work_package)
self.journal.log_rating(work_package, post_id=post.id, rating=rating.rating)
logger.info(f"Ranking {rating.rating} stored for work_package {work_package.id}.")
return reaction
@@ -193,8 +198,9 @@ class PromptRepository:
def store_ranking(self, ranking: protocol_schema.PostRanking) -> PostReaction:
# fetch work_package
work_package = self.fetch_workpackage_by_postid(ranking.post_id)
work_package.done = True
self.db.add(work_package)
if not work_package.collective:
work_package.done = True
self.db.add(work_package)
work_payload: db_payload.RankConversationRepliesPayload | db_payload.RankInitialPromptsPayload = (
work_package.payload.payload
@@ -250,6 +256,7 @@ class PromptRepository:
task: protocol_schema.Task,
thread_id: UUID = None,
parent_post_id: UUID = None,
collective: bool = False,
) -> WorkPackage:
payload: db_payload.TaskPayload
match type(task):
@@ -287,10 +294,7 @@ class PromptRepository:
raise OasstError(f"Invalid task type: {type(task)=}", OasstErrorCode.INVALID_TASK_TYPE)
wp = self.insert_work_package(
payload=payload,
id=task.id,
thread_id=thread_id,
parent_post_id=parent_post_id,
payload=payload, id=task.id, thread_id=thread_id, parent_post_id=parent_post_id, collective=collective
)
assert wp.id == task.id
return wp
@@ -301,6 +305,7 @@ class PromptRepository:
id: UUID = None,
thread_id: UUID = None,
parent_post_id: UUID = None,
collective: bool = False,
) -> WorkPackage:
c = PayloadContainer(payload=payload)
wp = WorkPackage(
@@ -311,6 +316,7 @@ class PromptRepository:
api_client_id=self.api_client.id,
thread_id=thread_id,
parent_post_id=parent_post_id,
collective=collective,
)
self.db.add(wp)
self.db.commit()
@@ -397,7 +403,7 @@ class PromptRepository:
distinct_threads = distinct_threads.filter(Post.role == require_role)
distinct_threads = distinct_threads.subquery()
random_thread = self.db.query(distinct_threads).order_by(func.random()).limit(1).subquery()
random_thread = self.db.query(distinct_threads).order_by(func.random()).limit(1)
thread_posts = self.db.query(Post).filter(Post.thread_id.in_(random_thread)).all()
return thread_posts
@@ -443,8 +449,10 @@ class PromptRepository:
if post_role:
parent = parent.filter(Post.role == post_role)
parent = parent.order_by(func.random()).limit(1).subquery()
parent = parent.order_by(func.random()).limit(1)
replies = self.db.query(Post).filter(Post.parent_id.in_(parent)).order_by(func.random()).limit(max_size).all()
if not replies:
raise OasstError("No replies found", OasstErrorCode.NO_REPLIES_FOUND)
thread = self.fetch_thread(replies[0].thread_id)
thread = {p.id: p for p in thread}
@@ -463,3 +471,20 @@ class PromptRepository:
def fetch_post(self, post_id: UUID) -> Optional[Post]:
return self.db.query(Post).filter(Post.id == post_id).one()
def close_task(self, post_id: str, allow_personal_tasks: bool = False):
self.validate_post_id(post_id)
wp = self.fetch_workpackage_by_postid(post_id)
if not wp:
raise OasstError("Work package not found", OasstErrorCode.WORK_PACKAGE_NOT_FOUND)
if wp.expired:
raise OasstError("Work package expired", OasstErrorCode.WORK_PACKAGE_EXPIRED)
if not allow_personal_tasks and not wp.collective:
raise OasstError("This is not a collective task", OasstErrorCode.WORK_PACKAGE_NOT_COLLECTIVE)
if wp.done:
raise OasstError("Allready closed", OasstErrorCode.WORK_PACKAGE_ALREADY_DONE)
wp.done = True
self.db.add(wp)
self.db.commit()
+9 -4
View File
@@ -52,14 +52,19 @@ class ApiClient:
return self.task_models_map[task_type].parse_obj(data)
def fetch_task(
self, task_type: protocol_schema.TaskRequestType, user: Optional[protocol_schema.User] = None
self,
task_type: protocol_schema.TaskRequestType,
user: Optional[protocol_schema.User] = None,
collective: bool = False,
) -> protocol_schema.Task:
req = protocol_schema.TaskRequest(type=task_type, user=user)
req = protocol_schema.TaskRequest(type=task_type, user=user, collective=collective)
data = self.post("/api/v1/tasks/", req.dict())
return self._parse_task(data)
def fetch_random_task(self, user: Optional[protocol_schema.User] = None) -> protocol_schema.Task:
return self.fetch_task(protocol_schema.TaskRequestType.random, user)
def fetch_random_task(
self, user: Optional[protocol_schema.User] = None, collective: bool = False
) -> protocol_schema.Task:
return self.fetch_task(protocol_schema.TaskRequestType.random, user, collective=collective)
def ack_task(self, task_id: str, post_id: str) -> None:
req = protocol_schema.TaskAck(post_id=post_id)
@@ -43,6 +43,7 @@ class TaskRequest(BaseModel):
type: TaskRequestType = TaskRequestType.random
user: Optional[User] = None
collective: bool = False
class TaskAck(BaseModel):
@@ -57,6 +58,12 @@ class TaskNAck(BaseModel):
reason: str
class TaskClose(BaseModel):
"""The frontend asks to mark task as done"""
post_id: str
class Task(BaseModel):
"""A task is a unit of work that the backend gives to the frontend."""
+9 -1
View File
@@ -1,3 +1,11 @@
{
"extends": "next/core-web-vitals"
"root": true,
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"next/core-web-vitals"
],
"rules": {
"sort-imports": "warn"
}
}
-8
View File
@@ -1,8 +0,0 @@
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
}
}
+271 -346
View File
@@ -51,6 +51,7 @@
"@storybook/testing-library": "^0.0.13",
"@types/node": "18.11.17",
"@types/react": "18.0.26",
"@typescript-eslint/eslint-plugin": "^5.47.1",
"babel-loader": "^8.3.0",
"eslint-plugin-storybook": "^0.6.8",
"prettier": "2.8.1",
@@ -3767,57 +3768,13 @@
"version": "13.1.0",
"license": "MIT"
},
"node_modules/@next/swc-android-arm-eabi": {
"version": "13.0.6",
"resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-13.0.6.tgz",
"integrity": "sha512-FGFSj3v2Bluw8fD/X+1eXIEB0PhoJE0zfutsAauRhmNpjjZshLDgoXMWm1jTRL/04K/o9gwwO2+A8+sPVCH1uw==",
"cpu": [
"arm"
],
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-android-arm64": {
"version": "13.0.6",
"resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-13.0.6.tgz",
"integrity": "sha512-7MgbtU7kimxuovVsd7jSJWMkIHBDBUsNLmmlkrBRHTvgzx5nDBXogP0hzZm7EImdOPwVMPpUHRQMBP9mbsiJYQ==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-darwin-arm64": {
"version": "13.0.6",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.0.6.tgz",
"integrity": "sha512-AUVEpVTxbP/fxdFsjVI9d5a0CFn6NVV7A/RXOb0Y+pXKIIZ1V5rFjPwpYfIfyOo2lrqgehMNQcyMRoTrhq04xg==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-darwin-x64": {
"version": "13.0.6",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.0.6.tgz",
"integrity": "sha512-SasCDJlshglsPnbzhWaIF6VEGkQy2NECcAOxPwaPr0cwbbt4aUlZ7QmskNzgolr5eAjFS/xTr7CEeKJtZpAAtQ==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
@@ -3826,141 +3783,6 @@
"node": ">= 10"
}
},
"node_modules/@next/swc-freebsd-x64": {
"version": "13.0.6",
"resolved": "https://registry.npmjs.org/@next/swc-freebsd-x64/-/swc-freebsd-x64-13.0.6.tgz",
"integrity": "sha512-6Lbxd9gAdXneTkwHyYW/qtX1Tdw7ND9UbiGsGz/SP43ZInNWnW6q0au4hEVPZ9bOWWRKzcVoeTBdoMpQk9Hx9w==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-linux-arm-gnueabihf": {
"version": "13.0.6",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-13.0.6.tgz",
"integrity": "sha512-wNdi5A519e1P+ozEuYOhWPzzE6m1y7mkO6NFwn6watUwO0X9nZs7fT9THmnekvmFQpaZ6U+xf2MQ9poQoCh6jQ==",
"cpu": [
"arm"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-linux-arm64-gnu": {
"version": "13.0.6",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.0.6.tgz",
"integrity": "sha512-e8KTRnleQY1KLk5PwGV5hrmvKksCc74QRpHl5ffWnEEAtL2FE0ave5aIkXqErsPdXkiKuA/owp3LjQrP+/AH7Q==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-linux-arm64-musl": {
"version": "13.0.6",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.0.6.tgz",
"integrity": "sha512-/7RF03C3mhjYpHN+pqOolgME3guiHU5T3TsejuyteqyEyzdEyLHod+jcYH6ft7UZ71a6TdOewvmbLOtzHW2O8A==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-linux-x64-gnu": {
"version": "13.0.6",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.0.6.tgz",
"integrity": "sha512-kxyEXnYHpOEkFnmrlwB1QlzJtjC6sAJytKcceIyFUHbCaD3W/Qb5tnclcnHKTaFccizZRePXvV25Ok/eUSpKTw==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-linux-x64-musl": {
"version": "13.0.6",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.0.6.tgz",
"integrity": "sha512-N0c6gubS3WW1oYYgo02xzZnNatfVQP/CiJq2ax+DJ55ePV62IACbRCU99TZNXXg+Kos6vNW4k+/qgvkvpGDeyA==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-win32-arm64-msvc": {
"version": "13.0.6",
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.0.6.tgz",
"integrity": "sha512-QjeMB2EBqBFPb/ac0CYr7GytbhUkrG4EwFWbcE0vsRp4H8grt25kYpFQckL4Jak3SUrp7vKfDwZ/SwO7QdO8vw==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-win32-ia32-msvc": {
"version": "13.0.6",
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.0.6.tgz",
"integrity": "sha512-EQzXtdqRTcmhT/tCq81rIwE36Y3fNHPInaCuJzM/kftdXfa0F+64y7FAoMO13npX8EG1+SamXgp/emSusKrCXg==",
"cpu": [
"ia32"
],
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-win32-x64-msvc": {
"version": "13.0.6",
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.0.6.tgz",
"integrity": "sha512-pSkqZ//UP/f2sS9T7IvHLfEWDPTX0vRyXJnAUNisKvO3eF3e1xdhDX7dix/X3Z3lnN4UjSwOzclAI87JFbOwmQ==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"license": "MIT",
@@ -8104,6 +7926,86 @@
"dev": true,
"license": "MIT"
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "5.47.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.47.1.tgz",
"integrity": "sha512-r4RZ2Jl9kcQN7K/dcOT+J7NAimbiis4sSM9spvWimsBvDegMhKLA5vri2jG19PmIPbDjPeWzfUPQ2hjEzA4Nmg==",
"dev": true,
"dependencies": {
"@typescript-eslint/scope-manager": "5.47.1",
"@typescript-eslint/type-utils": "5.47.1",
"@typescript-eslint/utils": "5.47.1",
"debug": "^4.3.4",
"ignore": "^5.2.0",
"natural-compare-lite": "^1.4.0",
"regexpp": "^3.2.0",
"semver": "^7.3.7",
"tsutils": "^3.21.0"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"@typescript-eslint/parser": "^5.0.0",
"eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": {
"version": "5.47.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.47.1.tgz",
"integrity": "sha512-9hsFDsgUwrdOoW1D97Ewog7DYSHaq4WKuNs0LHF9RiCmqB0Z+XRR4Pf7u7u9z/8CciHuJ6yxNws1XznI3ddjEw==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "5.47.1",
"@typescript-eslint/visitor-keys": "5.47.1"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": {
"version": "5.47.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.47.1.tgz",
"integrity": "sha512-CmALY9YWXEpwuu6377ybJBZdtSAnzXLSQcxLSqSQSbC7VfpMu/HLVdrnVJj7ycI138EHqocW02LPJErE35cE9A==",
"dev": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": {
"version": "5.47.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.47.1.tgz",
"integrity": "sha512-rF3pmut2JCCjh6BLRhNKdYjULMb1brvoaiWDlHfLNVgmnZ0sBVJrs3SyaKE1XoDDnJuAx/hDQryHYmPUuNq0ig==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "5.47.1",
"eslint-visitor-keys": "^3.3.0"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/parser": {
"version": "5.46.1",
"license": "BSD-2-Clause",
@@ -8144,6 +8046,90 @@
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/type-utils": {
"version": "5.47.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.47.1.tgz",
"integrity": "sha512-/UKOeo8ee80A7/GJA427oIrBi/Gd4osk/3auBUg4Rn9EahFpevVV1mUK8hjyQD5lHPqX397x6CwOk5WGh1E/1w==",
"dev": true,
"dependencies": {
"@typescript-eslint/typescript-estree": "5.47.1",
"@typescript-eslint/utils": "5.47.1",
"debug": "^4.3.4",
"tsutils": "^3.21.0"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"eslint": "*"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": {
"version": "5.47.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.47.1.tgz",
"integrity": "sha512-CmALY9YWXEpwuu6377ybJBZdtSAnzXLSQcxLSqSQSbC7VfpMu/HLVdrnVJj7ycI138EHqocW02LPJErE35cE9A==",
"dev": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": {
"version": "5.47.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.47.1.tgz",
"integrity": "sha512-4+ZhFSuISAvRi2xUszEj0xXbNTHceV9GbH9S8oAD2a/F9SW57aJNQVOCxG8GPfSWH/X4eOPdMEU2jYVuWKEpWA==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "5.47.1",
"@typescript-eslint/visitor-keys": "5.47.1",
"debug": "^4.3.4",
"globby": "^11.1.0",
"is-glob": "^4.0.3",
"semver": "^7.3.7",
"tsutils": "^3.21.0"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": {
"version": "5.47.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.47.1.tgz",
"integrity": "sha512-rF3pmut2JCCjh6BLRhNKdYjULMb1brvoaiWDlHfLNVgmnZ0sBVJrs3SyaKE1XoDDnJuAx/hDQryHYmPUuNq0ig==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "5.47.1",
"eslint-visitor-keys": "^3.3.0"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/types": {
"version": "5.46.1",
"license": "MIT",
@@ -9482,16 +9468,6 @@
"node": ">=8"
}
},
"node_modules/bindings": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
"dev": true,
"optional": true,
"dependencies": {
"file-uri-to-path": "1.0.0"
}
},
"node_modules/bl": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
@@ -12822,13 +12798,6 @@
"node": ">=12"
}
},
"node_modules/file-uri-to-path": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
"dev": true,
"optional": true
},
"node_modules/fill-range": {
"version": "7.0.1",
"license": "MIT",
@@ -13364,17 +13333,6 @@
"version": "1.0.0",
"license": "ISC"
},
"node_modules/fsevents": {
"version": "2.3.2",
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/function-bind": {
"version": "1.1.1",
"license": "MIT"
@@ -16151,13 +16109,6 @@
"version": "2.1.2",
"license": "MIT"
},
"node_modules/nan": {
"version": "2.17.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz",
"integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==",
"dev": true,
"optional": true
},
"node_modules/nanoid": {
"version": "3.3.4",
"license": "MIT",
@@ -16198,6 +16149,12 @@
"version": "1.4.0",
"license": "MIT"
},
"node_modules/natural-compare-lite": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz",
"integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
"dev": true
},
"node_modules/negotiator": {
"version": "0.6.3",
"dev": true,
@@ -21660,25 +21617,6 @@
"node": ">=0.10.0"
}
},
"node_modules/watchpack-chokidar2/node_modules/fsevents": {
"version": "1.2.13",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
"deprecated": "fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.",
"dev": true,
"hasInstallScript": true,
"optional": true,
"os": [
"darwin"
],
"dependencies": {
"bindings": "^1.5.0",
"nan": "^2.12.1"
},
"engines": {
"node": ">= 4.0"
}
},
"node_modules/watchpack-chokidar2/node_modules/glob-parent": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
@@ -24896,80 +24834,10 @@
"@next/font": {
"version": "13.1.0"
},
"@next/swc-android-arm-eabi": {
"version": "13.0.6",
"resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-13.0.6.tgz",
"integrity": "sha512-FGFSj3v2Bluw8fD/X+1eXIEB0PhoJE0zfutsAauRhmNpjjZshLDgoXMWm1jTRL/04K/o9gwwO2+A8+sPVCH1uw==",
"optional": true
},
"@next/swc-android-arm64": {
"version": "13.0.6",
"resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-13.0.6.tgz",
"integrity": "sha512-7MgbtU7kimxuovVsd7jSJWMkIHBDBUsNLmmlkrBRHTvgzx5nDBXogP0hzZm7EImdOPwVMPpUHRQMBP9mbsiJYQ==",
"optional": true
},
"@next/swc-darwin-arm64": {
"version": "13.0.6",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.0.6.tgz",
"integrity": "sha512-AUVEpVTxbP/fxdFsjVI9d5a0CFn6NVV7A/RXOb0Y+pXKIIZ1V5rFjPwpYfIfyOo2lrqgehMNQcyMRoTrhq04xg==",
"optional": true
},
"@next/swc-darwin-x64": {
"version": "13.0.6",
"optional": true
},
"@next/swc-freebsd-x64": {
"version": "13.0.6",
"resolved": "https://registry.npmjs.org/@next/swc-freebsd-x64/-/swc-freebsd-x64-13.0.6.tgz",
"integrity": "sha512-6Lbxd9gAdXneTkwHyYW/qtX1Tdw7ND9UbiGsGz/SP43ZInNWnW6q0au4hEVPZ9bOWWRKzcVoeTBdoMpQk9Hx9w==",
"optional": true
},
"@next/swc-linux-arm-gnueabihf": {
"version": "13.0.6",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-13.0.6.tgz",
"integrity": "sha512-wNdi5A519e1P+ozEuYOhWPzzE6m1y7mkO6NFwn6watUwO0X9nZs7fT9THmnekvmFQpaZ6U+xf2MQ9poQoCh6jQ==",
"optional": true
},
"@next/swc-linux-arm64-gnu": {
"version": "13.0.6",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.0.6.tgz",
"integrity": "sha512-e8KTRnleQY1KLk5PwGV5hrmvKksCc74QRpHl5ffWnEEAtL2FE0ave5aIkXqErsPdXkiKuA/owp3LjQrP+/AH7Q==",
"optional": true
},
"@next/swc-linux-arm64-musl": {
"version": "13.0.6",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.0.6.tgz",
"integrity": "sha512-/7RF03C3mhjYpHN+pqOolgME3guiHU5T3TsejuyteqyEyzdEyLHod+jcYH6ft7UZ71a6TdOewvmbLOtzHW2O8A==",
"optional": true
},
"@next/swc-linux-x64-gnu": {
"version": "13.0.6",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.0.6.tgz",
"integrity": "sha512-kxyEXnYHpOEkFnmrlwB1QlzJtjC6sAJytKcceIyFUHbCaD3W/Qb5tnclcnHKTaFccizZRePXvV25Ok/eUSpKTw==",
"optional": true
},
"@next/swc-linux-x64-musl": {
"version": "13.0.6",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.0.6.tgz",
"integrity": "sha512-N0c6gubS3WW1oYYgo02xzZnNatfVQP/CiJq2ax+DJ55ePV62IACbRCU99TZNXXg+Kos6vNW4k+/qgvkvpGDeyA==",
"optional": true
},
"@next/swc-win32-arm64-msvc": {
"version": "13.0.6",
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.0.6.tgz",
"integrity": "sha512-QjeMB2EBqBFPb/ac0CYr7GytbhUkrG4EwFWbcE0vsRp4H8grt25kYpFQckL4Jak3SUrp7vKfDwZ/SwO7QdO8vw==",
"optional": true
},
"@next/swc-win32-ia32-msvc": {
"version": "13.0.6",
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.0.6.tgz",
"integrity": "sha512-EQzXtdqRTcmhT/tCq81rIwE36Y3fNHPInaCuJzM/kftdXfa0F+64y7FAoMO13npX8EG1+SamXgp/emSusKrCXg==",
"optional": true
},
"@next/swc-win32-x64-msvc": {
"version": "13.0.6",
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.0.6.tgz",
"integrity": "sha512-pSkqZ//UP/f2sS9T7IvHLfEWDPTX0vRyXJnAUNisKvO3eF3e1xdhDX7dix/X3Z3lnN4UjSwOzclAI87JFbOwmQ==",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.0.6.tgz",
"integrity": "sha512-SasCDJlshglsPnbzhWaIF6VEGkQy2NECcAOxPwaPr0cwbbt4aUlZ7QmskNzgolr5eAjFS/xTr7CEeKJtZpAAtQ==",
"optional": true
},
"@nodelib/fs.scandir": {
@@ -27741,6 +27609,51 @@
"version": "21.0.0",
"dev": true
},
"@typescript-eslint/eslint-plugin": {
"version": "5.47.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.47.1.tgz",
"integrity": "sha512-r4RZ2Jl9kcQN7K/dcOT+J7NAimbiis4sSM9spvWimsBvDegMhKLA5vri2jG19PmIPbDjPeWzfUPQ2hjEzA4Nmg==",
"dev": true,
"requires": {
"@typescript-eslint/scope-manager": "5.47.1",
"@typescript-eslint/type-utils": "5.47.1",
"@typescript-eslint/utils": "5.47.1",
"debug": "^4.3.4",
"ignore": "^5.2.0",
"natural-compare-lite": "^1.4.0",
"regexpp": "^3.2.0",
"semver": "^7.3.7",
"tsutils": "^3.21.0"
},
"dependencies": {
"@typescript-eslint/scope-manager": {
"version": "5.47.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.47.1.tgz",
"integrity": "sha512-9hsFDsgUwrdOoW1D97Ewog7DYSHaq4WKuNs0LHF9RiCmqB0Z+XRR4Pf7u7u9z/8CciHuJ6yxNws1XznI3ddjEw==",
"dev": true,
"requires": {
"@typescript-eslint/types": "5.47.1",
"@typescript-eslint/visitor-keys": "5.47.1"
}
},
"@typescript-eslint/types": {
"version": "5.47.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.47.1.tgz",
"integrity": "sha512-CmALY9YWXEpwuu6377ybJBZdtSAnzXLSQcxLSqSQSbC7VfpMu/HLVdrnVJj7ycI138EHqocW02LPJErE35cE9A==",
"dev": true
},
"@typescript-eslint/visitor-keys": {
"version": "5.47.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.47.1.tgz",
"integrity": "sha512-rF3pmut2JCCjh6BLRhNKdYjULMb1brvoaiWDlHfLNVgmnZ0sBVJrs3SyaKE1XoDDnJuAx/hDQryHYmPUuNq0ig==",
"dev": true,
"requires": {
"@typescript-eslint/types": "5.47.1",
"eslint-visitor-keys": "^3.3.0"
}
}
}
},
"@typescript-eslint/parser": {
"version": "5.46.1",
"requires": {
@@ -27757,6 +27670,51 @@
"@typescript-eslint/visitor-keys": "5.46.1"
}
},
"@typescript-eslint/type-utils": {
"version": "5.47.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.47.1.tgz",
"integrity": "sha512-/UKOeo8ee80A7/GJA427oIrBi/Gd4osk/3auBUg4Rn9EahFpevVV1mUK8hjyQD5lHPqX397x6CwOk5WGh1E/1w==",
"dev": true,
"requires": {
"@typescript-eslint/typescript-estree": "5.47.1",
"@typescript-eslint/utils": "5.47.1",
"debug": "^4.3.4",
"tsutils": "^3.21.0"
},
"dependencies": {
"@typescript-eslint/types": {
"version": "5.47.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.47.1.tgz",
"integrity": "sha512-CmALY9YWXEpwuu6377ybJBZdtSAnzXLSQcxLSqSQSbC7VfpMu/HLVdrnVJj7ycI138EHqocW02LPJErE35cE9A==",
"dev": true
},
"@typescript-eslint/typescript-estree": {
"version": "5.47.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.47.1.tgz",
"integrity": "sha512-4+ZhFSuISAvRi2xUszEj0xXbNTHceV9GbH9S8oAD2a/F9SW57aJNQVOCxG8GPfSWH/X4eOPdMEU2jYVuWKEpWA==",
"dev": true,
"requires": {
"@typescript-eslint/types": "5.47.1",
"@typescript-eslint/visitor-keys": "5.47.1",
"debug": "^4.3.4",
"globby": "^11.1.0",
"is-glob": "^4.0.3",
"semver": "^7.3.7",
"tsutils": "^3.21.0"
}
},
"@typescript-eslint/visitor-keys": {
"version": "5.47.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.47.1.tgz",
"integrity": "sha512-rF3pmut2JCCjh6BLRhNKdYjULMb1brvoaiWDlHfLNVgmnZ0sBVJrs3SyaKE1XoDDnJuAx/hDQryHYmPUuNq0ig==",
"dev": true,
"requires": {
"@typescript-eslint/types": "5.47.1",
"eslint-visitor-keys": "^3.3.0"
}
}
}
},
"@typescript-eslint/types": {
"version": "5.46.1"
},
@@ -28640,16 +28598,6 @@
"binary-extensions": {
"version": "2.2.0"
},
"bindings": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
"dev": true,
"optional": true,
"requires": {
"file-uri-to-path": "1.0.0"
}
},
"bl": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
@@ -30956,13 +30904,6 @@
}
}
},
"file-uri-to-path": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
"dev": true,
"optional": true
},
"fill-range": {
"version": "7.0.1",
"requires": {
@@ -31351,10 +31292,6 @@
"fs.realpath": {
"version": "1.0.0"
},
"fsevents": {
"version": "2.3.2",
"optional": true
},
"function-bind": {
"version": "1.1.1"
},
@@ -33122,13 +33059,6 @@
"ms": {
"version": "2.1.2"
},
"nan": {
"version": "2.17.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz",
"integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==",
"dev": true,
"optional": true
},
"nanoid": {
"version": "3.3.4"
},
@@ -33157,6 +33087,12 @@
"natural-compare": {
"version": "1.4.0"
},
"natural-compare-lite": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz",
"integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
"dev": true
},
"negotiator": {
"version": "0.6.3",
"dev": true
@@ -36772,17 +36708,6 @@
}
}
},
"fsevents": {
"version": "1.2.13",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
"dev": true,
"optional": true,
"requires": {
"bindings": "^1.5.0",
"nan": "^2.12.1"
}
},
"glob-parent": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
+1
View File
@@ -57,6 +57,7 @@
"@types/react": "18.0.26",
"babel-loader": "^8.3.0",
"eslint-plugin-storybook": "^0.6.8",
"@typescript-eslint/eslint-plugin": "^5.47.1",
"prettier": "2.8.1",
"prisma": "^4.7.1",
"typescript": "4.9.4"
-19
View File
@@ -1,19 +0,0 @@
import clsx from "clsx";
export const Button = (
props: React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>
) => {
const { className, children, ...rest } = props;
return (
<button
type="button"
className={clsx(
"inline-flex items-center rounded-md border border-transparent px-4 py-2 text-sm font-medium focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2",
className
)}
{...rest}
>
{children}
</button>
);
};
+9
View File
@@ -0,0 +1,9 @@
import { Button, ButtonProps } from "@chakra-ui/react";
export const SkipButton = ({ children, ...props }: ButtonProps) => {
return (
<Button size="lg" variant="outline" {...props}>
{children}
</Button>
);
};
@@ -0,0 +1,9 @@
import { Button, ButtonProps } from "@chakra-ui/react";
export const SubmitButton = ({ children, ...props }: ButtonProps) => {
return (
<Button size="lg" variant="solid" {...props}>
{children}
</Button>
);
};
+1 -1
View File
@@ -1,7 +1,7 @@
import { useId } from "react";
export function CircleBackground({ color, width = 558, height = 558, ...props }) {
let id = useId();
const id = useId();
return (
<svg viewBox="0 0 558 558" width={width} height={height} fill="none" aria-hidden="true" {...props}>
+12 -10
View File
@@ -34,17 +34,19 @@ export function Footer() {
</Link>
</div>
</div>
<div className="flex flex-col text-sm leading-7">
<b>Legal</b>
<div className="flex flex-col leading-5">
<Link href="#" aria-label="Privacy Policy" className="hover:underline underline-offset-2">
Privacy Policy
</Link>
<Link href="#" aria-label="Terms of Service" className="hover:underline underline-offset-2">
Terms of Service
</Link>
<nav className="flex justify-center gap-20">
<div className="flex flex-col text-sm leading-7">
<b>Information</b>
<div className="flex flex-col leading-5">
<Link href="#" aria-label="Our Team" className="hover:underline underline-offset-2">
Our Team
</Link>
<Link href="/#join-us" aria-label="Join Us" className="hover:underline underline-offset-2">
Join Us
</Link>
</div>
</div>
</div>
</nav>
<div className="flex flex-col text-sm leading-7">
<b>Connect</b>
<div className="flex flex-col leading-5">
+2 -2
View File
@@ -100,8 +100,8 @@ export function Header(props) {
className="absolute inset-x-0 top-0 z-0 origin-top rounded-b-2xl bg-white px-6 pb-6 pt-32 shadow-2xl shadow-gray-900/20"
>
<div className="space-y-4">
<MobileNavLink href="#join-us">Join Us</MobileNavLink>
<MobileNavLink href="#faqs">FAQs</MobileNavLink>
<MobileNavLink href="/#join-us">Join Us</MobileNavLink>
<MobileNavLink href="/#faqs">FAQs</MobileNavLink>
</div>
<div className="mt-8 flex flex-col gap-4"></div>
</Popover.Panel>
+3 -3
View File
@@ -3,13 +3,13 @@ import Link from "next/link";
import { AnimatePresence, motion } from "framer-motion";
export function NavLinks(): JSX.Element {
let [hoveredIndex, setHoveredIndex] = useState(null);
const [hoveredIndex, setHoveredIndex] = useState(null);
return (
<>
{[
["Join Us", "#join-us"],
["FAQ", "#faq"],
["Join Us", "/#join-us"],
["FAQ", "/#faq"],
].map(([label, href], index) => (
<Link
key={label}
+1 -1
View File
@@ -3,7 +3,7 @@ import { signOut, useSession } from "next-auth/react";
import Image from "next/image";
import { Popover } from "@headlessui/react";
import { AnimatePresence, motion } from "framer-motion";
import { FaCog, FaSignOutAlt, FaGithub } from "react-icons/fa";
import { FaCog, FaSignOutAlt } from "react-icons/fa";
import { Box, useColorModeValue } from "@chakra-ui/react";
export function UserMenu() {
+1 -1
View File
@@ -5,7 +5,7 @@ import type { NextPage } from "next";
import { Footer } from "./Footer";
import { Header } from "src/components/Header";
export type NextPageWithLayout<P = {}, IP = P> = NextPage<P, IP> & {
export type NextPageWithLayout<P = unknown, IP = P> = NextPage<P, IP> & {
getLayout?: (page: React.ReactElement) => React.ReactNode;
};
@@ -0,0 +1,48 @@
import { ReactNode, useEffect, useState } from "react";
import { SortableItem } from "./SortableItem";
export interface SortableProps {
items: ReactNode[];
onChange: (newSortedIndices: number[]) => void;
}
export const Sortable = ({ items, onChange }) => {
const [sortOrder, setSortOrder] = useState<number[]>([]);
const update = (newRanking: number[]) => {
setSortOrder(newRanking);
onChange(newRanking);
};
useEffect(() => {
const indices = Array.from({ length: items.length }).map((_, i) => i);
setSortOrder(indices);
onChange(indices);
}, [items, onChange]);
return (
<ul className="flex flex-col gap-4">
{sortOrder.map((rank, i) => (
<SortableItem
key={`${rank}`}
canIncrement={i > 0}
onIncrement={() => {
const newRanking = sortOrder.slice();
const newIdx = i - 1;
[newRanking[i], newRanking[newIdx]] = [newRanking[newIdx], newRanking[i]];
update(newRanking);
}}
canDecrement={i < sortOrder.length - 1}
onDecrement={() => {
const newRanking = sortOrder.slice();
const newIdx = i + 1;
[newRanking[i], newRanking[newIdx]] = [newRanking[newIdx], newRanking[i]];
update(newRanking);
}}
>
{items[rank]}
</SortableItem>
))}
</ul>
);
};
@@ -0,0 +1,40 @@
import { ArrowUpIcon, ArrowDownIcon } from "@heroicons/react/20/solid";
import { Button } from "@chakra-ui/react";
import clsx from "clsx";
export interface SortableItemProps {
canIncrement: boolean;
canDecrement: boolean;
onIncrement: () => void;
onDecrement: () => void;
children: React.ReactNode;
}
export const SortableItem = ({ canIncrement, canDecrement, onIncrement, onDecrement, children }: SortableItemProps) => {
return (
<li className="grid grid-cols-[min-content_1fr] items-center rounded-lg shadow-md gap-x-2 p-2">
<ArrowButton active={canIncrement} onClick={onIncrement}>
<ArrowUpIcon width={28} />
</ArrowButton>
<span style={{ gridRow: "span 2" }}>{children}</span>
<ArrowButton active={canDecrement} onClick={onDecrement}>
<ArrowDownIcon width={28} />
</ArrowButton>
</li>
);
};
interface ArrowButtonProps {
active: boolean;
onClick: () => void;
children: React.ReactNode;
}
const ArrowButton = ({ children, active, onClick }: ArrowButtonProps) => {
return (
<Button justifyContent="center" variant="ghost" onClick={onClick} disabled={!active}>
{children}
</Button>
);
};
@@ -0,0 +1,10 @@
export const TaskInfo = ({ id, output }: { id: string; output: any }) => {
return (
<div className="grid grid-cols-[min-content_auto] gap-x-2 text-gray-700">
<b>Prompt</b>
<span>{id}</span>
<b>Output</b>
<span>{output}</span>
</div>
);
};
@@ -34,6 +34,18 @@ export const TaskSelection = () => {
title="Rank Initial Prompts"
link="/evaluate/rank_initial_prompts"
/>
<TaskOption
alt="Rank User Replies"
img="/images/logos/logo.svg"
title="Rank User Replies"
link="/evaluate/rank_user_replies"
/>
<TaskOption
alt="Rank Assistant Replies"
img="/images/logos/logo.svg"
title="Rank Assistant Replies"
link="/evaluate/rank_assistant_replies"
/>
</TaskOptions>
</Flex>
);
+3 -3
View File
@@ -1,10 +1,10 @@
import { PrismaClient } from "@prisma/client";
declare global {
var prisma;
// eslint-disable-next-line no-var
var prisma: PrismaClient | undefined;
}
const client = globalThis.prisma || new PrismaClient();
const client = new PrismaClient();
if (process.env.NODE_ENV !== "production") {
globalThis.prisma = client;
}
+1 -1
View File
@@ -1,7 +1,7 @@
import { SessionProvider } from "next-auth/react";
import type { AppProps } from "next/app";
import { getDefaultLayout, NextPageWithLayout } from "src/components/Layout";
import { NextPageWithLayout, getDefaultLayout } from "src/components/Layout";
import "../styles/globals.css";
import "focus-visible";
+30 -16
View File
@@ -1,19 +1,26 @@
import { Button, Input, Stack } from "@chakra-ui/react";
import Head from "next/head";
import { FaDiscord, FaEnvelope, FaGithub } from "react-icons/fa";
import { FaDiscord, FaEnvelope, FaGithub, FaBug } from "react-icons/fa";
import { getCsrfToken, getProviders, signIn } from "next-auth/react";
import { useRef } from "react";
import React, { useRef } from "react";
import Link from "next/link";
import { AuthLayout } from "src/components/AuthLayout";
export default function Signin({ csrfToken, providers }) {
const { discord, email, github } = providers;
const { discord, email, github, credentials } = providers;
const emailEl = useRef(null);
const signinWithEmail = () => {
const signinWithEmail = (ev: React.FormEvent) => {
ev.preventDefault();
signIn(email.id, { callbackUrl: "/", email: emailEl.current.value });
};
const debugUsernameEl = useRef(null);
function signinWithDebugCredentials(ev: React.FormEvent) {
ev.preventDefault();
signIn(credentials.id, { callbackUrl: "/", username: debugUsernameEl.current.value });
}
return (
<>
<Head>
@@ -22,19 +29,26 @@ export default function Signin({ csrfToken, providers }) {
</Head>
<AuthLayout>
<Stack spacing="2">
{credentials && (
<form onSubmit={signinWithDebugCredentials} className="border-2 border-orange-200 rounded-md p-4 relative">
<span className="text-orange-600 absolute -top-3 left-5 bg-white px-1">For Debugging Only</span>
<Stack>
<Input variant="outline" size="lg" placeholder="Username" ref={debugUsernameEl} />
<Button size={"lg"} leftIcon={<FaBug />} colorScheme="gray" type="submit">
Continue with Debug User
</Button>
</Stack>
</form>
)}
{email && (
<Stack>
<Input variant="outline" size="lg" placeholder="Email Address" ref={emailEl} />
<Button
size={"lg"}
leftIcon={<FaEnvelope />}
colorScheme="gray"
onClick={signinWithEmail}
// isDisabled="false"
>
Continue with Email
</Button>
</Stack>
<form onSubmit={signinWithEmail}>
<Stack>
<Input variant="outline" size="lg" placeholder="Email Address" ref={emailEl} />
<Button size={"lg"} leftIcon={<FaEnvelope />} colorScheme="gray" type="submit">
Continue with Email
</Button>
</Stack>
</form>
)}
{discord && (
<Button
+10 -17
View File
@@ -1,14 +1,17 @@
import { Container, Textarea } from "@chakra-ui/react";
import { Container, Flex, Textarea } from "@chakra-ui/react";
import { useRef, useState } from "react";
import useSWRMutation from "swr/mutation";
import useSWRImmutable from "swr/immutable";
import fetcher from "src/lib/fetcher";
import poster from "src/lib/poster";
import { Messages } from "src/components/Messages";
import { TwoColumns } from "src/components/TwoColumns";
import { Button } from "src/components/Button";
import { LoadingScreen } from "src/components/Loading/LoadingScreen";
import { TaskInfo } from "src/components/TaskInfo/TaskInfo";
import { SkipButton } from "src/components/Buttons/Skip";
import { SubmitButton } from "src/components/Buttons/Submit";
const AssistantReply = () => {
const [tasks, setTasks] = useState([]);
@@ -61,22 +64,12 @@ const AssistantReply = () => {
</TwoColumns>
<section className="mb-8 p-4 rounded-lg shadow-lg bg-white flex flex-row justify-items-stretch ">
<div className="grid grid-cols-[min-content_auto] gap-x-2 text-gray-700">
<b>Prompt</b>
<span>{tasks[0].id}</span>
<b>Output</b>
<span>Submit your answer</span>
</div>
<TaskInfo id={tasks[0].id} output="Submit your answer" />
<div className="flex justify-center ml-auto">
<Button className="mr-2 bg-indigo-100 text-indigo-700 hover:bg-indigo-200">Skip</Button>
<Button
onClick={() => submitResponse(tasks[0])}
className="bg-indigo-600 text-white shadow-sm hover:bg-indigo-700"
>
Submit
</Button>
</div>
<Flex justify="center" ml="auto" gap={2}>
<SkipButton>Skip</SkipButton>
<SubmitButton onClick={() => submitResponse(tasks[0])}>Submit</SubmitButton>
</Flex>
</section>
</Container>
);
+10 -18
View File
@@ -1,4 +1,4 @@
import { Textarea } from "@chakra-ui/react";
import { Flex, Textarea } from "@chakra-ui/react";
import Head from "next/head";
import { useRef, useState } from "react";
import useSWRImmutable from "swr/immutable";
@@ -7,9 +7,11 @@ import useSWRMutation from "swr/mutation";
import fetcher from "src/lib/fetcher";
import poster from "src/lib/poster";
import { LoadingScreen } from "src/components/Loading/LoadingScreen";
import { TwoColumns } from "src/components/TwoColumns";
import { Button } from "src/components/Button";
import { LoadingScreen } from "@/components/Loading/LoadingScreen";
import { TaskInfo } from "src/components/TaskInfo/TaskInfo";
import { SkipButton } from "src/components/Buttons/Skip";
import { SubmitButton } from "src/components/Buttons/Submit";
const SummarizeStory = () => {
// Use an array of tasks that record the sequence of steps until a task is
@@ -75,22 +77,12 @@ const SummarizeStory = () => {
</TwoColumns>
<section className="mb-8 p-4 rounded-lg shadow-lg bg-white flex flex-row justify-items-stretch ">
<div className="grid grid-cols-[min-content_auto] gap-x-2 text-gray-700">
<b>Prompt</b>
<span>{tasks[0].id}</span>
<b>Output</b>
<span>Submit your answer</span>
</div>
<TaskInfo id={tasks[0].id} output="Submit your answer" />
<div className="flex justify-center ml-auto">
<Button className="mr-2 bg-indigo-100 text-indigo-700 hover:bg-indigo-200">Skip</Button>
<Button
onClick={() => submitResponse(tasks[0])}
className="bg-indigo-600 text-white shadow-sm hover:bg-indigo-700"
>
Submit
</Button>
</div>
<Flex justify="center" ml="auto" gap={2}>
<SkipButton>Skip</SkipButton>
<SubmitButton onClick={() => submitResponse(tasks[0])}>Submit</SubmitButton>
</Flex>
</section>
</main>
</>
+13 -20
View File
@@ -1,14 +1,17 @@
import { Container, Textarea, useColorModeValue } from "@chakra-ui/react";
import { Container, Flex, Textarea, useColorModeValue } from "@chakra-ui/react";
import { useRef, useState } from "react";
import useSWRMutation from "swr/mutation";
import useSWRImmutable from "swr/immutable";
import fetcher from "src/lib/fetcher";
import poster from "src/lib/poster";
import { LoadingScreen } from "src/components/Loading/LoadingScreen";
import { Messages } from "src/components/Messages";
import { TaskInfo } from "src/components/TaskInfo/TaskInfo";
import { TwoColumns } from "src/components/TwoColumns";
import { Button } from "src/components/Button";
import { LoadingScreen } from "@/components/Loading/LoadingScreen";
import { SkipButton } from "src/components/Buttons/Skip";
import { SubmitButton } from "src/components/Buttons/Submit";
const UserReply = () => {
const [tasks, setTasks] = useState([]);
@@ -62,24 +65,14 @@ const UserReply = () => {
<Textarea name="reply" placeholder="Reply..." ref={inputRef} />
</TwoColumns>
<Container bg={bg} className="p-4 rounded-lg shadow-lg flex flex-row justify-items-stretch">
<div className="grid grid-cols-[min-content_auto] gap-x-2 text-gray-700">
<b>Prompt</b>
<span>{tasks[0].id}</span>
<b>Output</b>
<span>Submit your answer</span>
</div>
<section className="mb-8 p-4 rounded-lg shadow-lg bg-white flex flex-row justify-items-stretch ">
<TaskInfo id={tasks[0].id} output="Submit your answer" />
<div className="flex justify-center ml-auto">
<Button className="mr-2 bg-indigo-100 text-indigo-700 hover:bg-indigo-200">Skip</Button>
<Button
onClick={() => submitResponse(tasks[0])}
className="bg-indigo-600 text-white shadow-sm hover:bg-indigo-700"
>
Submit
</Button>
</div>
</Container>
<Flex justify="center" ml="auto" gap={2}>
<SkipButton>Skip</SkipButton>
<SubmitButton onClick={() => submitResponse(tasks[0])}>Submit</SubmitButton>
</Flex>
</section>
</Container>
);
};
@@ -0,0 +1,86 @@
import { Button, Flex } from "@chakra-ui/react";
import Head from "next/head";
import { useState } from "react";
import useSWRImmutable from "swr/immutable";
import useSWRMutation from "swr/mutation";
import fetcher from "src/lib/fetcher";
import poster from "src/lib/poster";
import { LoadingScreen } from "src/components/Loading/LoadingScreen";
import { Sortable } from "src/components/Sortable/Sortable";
import { TaskInfo } from "src/components/TaskInfo/TaskInfo";
import { SubmitButton } from "src/components/Buttons/Submit";
import { SkipButton } from "src/components/Buttons/Skip";
const RankAssistantReplies = () => {
const [tasks, setTasks] = useState([]);
/**
* This array will contain the ranked indices of the replies
* The best reply will have index 0, and the worst is the last.
*/
const [ranking, setRanking] = useState<number[]>([]);
const { isLoading } = useSWRImmutable("/api/new_task/rank_assistant_replies", fetcher, {
onSuccess: (data) => {
setTasks([data]);
},
});
const { trigger, isMutating } = useSWRMutation("/api/update_task", poster, {
onSuccess: async (data) => {
const newTask = await data.json();
setTasks((oldTasks) => [...oldTasks, newTask]);
},
});
const submitResponse = (task) => {
trigger({
id: task.id,
update_type: "post_ranking",
content: {
ranking,
},
});
};
if (isLoading) {
return <LoadingScreen text="Loading..." />;
}
if (tasks.length == 0) {
return <div className="p-6 bg-slate-100 text-gray-800">Loading...</div>;
}
const replies = tasks[0].task.replies as string[];
return (
<>
<Head>
<title>Rank Assistant Replies</title>
<meta name="description" content="Rank Assistant Replies." />
</Head>
<main className="p-6 bg-slate-100 text-gray-800">
<div className="rounded-lg shadow-lg block bg-white p-6 mb-8">
<h5 className="text-lg font-semibold mb-4">Instructions</h5>
<p className="text-lg py-1">
Given the following replies, sort them from best to worst, best being first, worst being last.
</p>
<Sortable items={replies} onChange={setRanking} />
</div>
<section className="mb-8 p-4 rounded-lg shadow-lg bg-white flex flex-row justify-items-stretch">
<TaskInfo id={tasks[0].id} output="Submit your answer" />
<Flex justify="center" ml="auto" gap={2}>
<SkipButton>Skip</SkipButton>
<SubmitButton onClick={() => submitResponse(tasks[0])} disabled={ranking.length === 0}>
Submit
</SubmitButton>
</Flex>
</section>
</main>
</>
);
};
export default RankAssistantReplies;
@@ -1,5 +1,4 @@
import { ArrowUpIcon, ArrowDownIcon } from "@heroicons/react/20/solid";
import clsx from "clsx";
import { Flex } from "@chakra-ui/react";
import Head from "next/head";
import { useState } from "react";
import useSWRImmutable from "swr/immutable";
@@ -8,9 +7,12 @@ import useSWRMutation from "swr/mutation";
import fetcher from "src/lib/fetcher";
import poster from "src/lib/poster";
import { Button } from "src/components/Button";
import { LoadingScreen } from "@/components/Loading/LoadingScreen";
import { Container, useColorModeValue } from "@chakra-ui/react";
import { LoadingScreen } from "src/components/Loading/LoadingScreen";
import { Sortable } from "src/components/Sortable/Sortable";
import { TaskInfo } from "src/components/TaskInfo/TaskInfo";
import { SkipButton } from "src/components/Buttons/Skip";
import { SubmitButton } from "src/components/Buttons/Submit";
const RankInitialPrompts = () => {
const [tasks, setTasks] = useState([]);
@@ -24,9 +26,6 @@ const RankInitialPrompts = () => {
const { isLoading } = useSWRImmutable("/api/new_task/rank_initial_prompts", fetcher, {
onSuccess: (data) => {
setTasks([data]);
const indices = Array.from({ length: data.task.prompts.length }).map((_, i) => i);
setRanking(indices);
},
});
@@ -55,12 +54,6 @@ const RankInitialPrompts = () => {
return <Container className="p-6 bg-slate-100 text-gray-800">No tasks found...</Container>;
}
const prompts = tasks[0].task.prompts as string[];
const items = ranking.map((i) => ({
text: prompts[i],
originalIndex: i,
}));
return (
<>
<Head>
@@ -73,49 +66,18 @@ const RankInitialPrompts = () => {
<p className="text-lg py-1">
Given the following prompts, sort them from best to worst, best being first, worst being last.
</p>
<ul className="flex flex-col gap-4">
{items.map(({ text, originalIndex }, i) => (
<SortableItem
key={`${originalIndex}_${i}`}
canIncrement={i > 0}
onIncrement={() => {
const newRanking = ranking.slice();
const newIdx = i - 1;
[newRanking[i], newRanking[newIdx]] = [newRanking[newIdx], newRanking[i]];
setRanking(newRanking);
}}
canDecrement={i < items.length - 1}
onDecrement={() => {
const newRanking = ranking.slice();
const newIdx = i + 1;
[newRanking[i], newRanking[newIdx]] = [newRanking[newIdx], newRanking[i]];
setRanking(newRanking);
}}
>
{text}
</SortableItem>
))}
</ul>
<Sortable items={tasks[0].task.prompts} onChange={setRanking} />
</Container>
<section className="mb-8 p-4 rounded-lg shadow-lg bg-white flex flex-row justify-items-stretch ">
<div className="grid grid-cols-[min-content_auto] gap-x-2 text-gray-700">
<b>Prompt</b>
<span>{tasks[0].id}</span>
<b>Output</b>
<span>Submit your answer</span>
</div>
<section className="mb-8 p-4 rounded-lg shadow-lg bg-white flex flex-row justify-items-stretch">
<TaskInfo id={tasks[0].id} output="Submit your answer" />
<div className="flex justify-center ml-auto">
<Button className="mr-2 bg-indigo-100 text-indigo-700 hover:bg-indigo-200">Skip</Button>
<Button
onClick={() => submitResponse(tasks[0])}
disabled={ranking.length === 0}
className="bg-indigo-600 text-white shadow-sm hover:bg-indigo-700"
>
<Flex justify="center" ml="auto" gap={2}>
<SkipButton>Skip</SkipButton>
<SubmitButton onClick={() => submitResponse(tasks[0])} disabled={ranking.length === 0}>
Submit
</Button>
</div>
</SubmitButton>
</Flex>
</section>
</Container>
</>
@@ -123,30 +85,3 @@ const RankInitialPrompts = () => {
};
export default RankInitialPrompts;
const SortableItem = ({ canIncrement, canDecrement, onIncrement, onDecrement, children, ...props }) => {
return (
<li className="grid grid-cols-[min-content_1fr] items-center rounded-lg shadow-md gap-x-2 p-2">
<ArrowButton active={canIncrement} onClick={onIncrement}>
<ArrowUpIcon width={28} />
</ArrowButton>
<span style={{ gridRow: "span 2" }}>{children}</span>
<ArrowButton active={canDecrement} onClick={onDecrement}>
<ArrowDownIcon width={28} />
</ArrowButton>
</li>
);
};
const ArrowButton = ({ children, active, onClick }) => {
return (
<Button
className={clsx("justify-center", active ? "hover:bg-indigo-200" : "opacity-10")}
onClick={onClick}
disabled={!active}
>
{children}
</Button>
);
};
@@ -0,0 +1,86 @@
import Head from "next/head";
import { useState } from "react";
import useSWRImmutable from "swr/immutable";
import useSWRMutation from "swr/mutation";
import fetcher from "src/lib/fetcher";
import poster from "src/lib/poster";
import { LoadingScreen } from "src/components/Loading/LoadingScreen";
import { Sortable } from "src/components/Sortable/Sortable";
import { TaskInfo } from "src/components/TaskInfo/TaskInfo";
import { Flex } from "@chakra-ui/react";
import { SkipButton } from "src/components/Buttons/Skip";
import { SubmitButton } from "src/components/Buttons/Submit";
const RankUserReplies = () => {
const [tasks, setTasks] = useState([]);
/**
* This array will contain the ranked indices of the replies
* The best reply will have index 0, and the worst is the last.
*/
const [ranking, setRanking] = useState<number[]>([]);
const { isLoading } = useSWRImmutable("/api/new_task/rank_user_replies", fetcher, {
onSuccess: (data) => {
setTasks([data]);
},
});
const { trigger, isMutating } = useSWRMutation("/api/update_task", poster, {
onSuccess: async (data) => {
const newTask = await data.json();
setTasks((oldTasks) => [...oldTasks, newTask]);
},
});
const submitResponse = (task) => {
trigger({
id: task.id,
update_type: "post_ranking",
content: {
ranking,
},
});
};
if (isLoading) {
return <LoadingScreen text="Loading..." />;
}
if (tasks.length == 0) {
return <div className="p-6 bg-slate-100 text-gray-800">Loading...</div>;
}
const replies = tasks[0].task.replies as string[];
return (
<>
<Head>
<title>Rank User Replies</title>
<meta name="description" content="Rank User Replies." />
</Head>
<main className="p-6 bg-slate-100 text-gray-800">
<div className="rounded-lg shadow-lg block bg-white p-6 mb-8">
<h5 className="text-lg font-semibold mb-4">Instructions</h5>
<p className="text-lg py-1">
Given the following replies, sort them from best to worst, best being first, worst being last.
</p>
<Sortable items={replies} onChange={setRanking} />
</div>
<section className="mb-8 p-4 rounded-lg shadow-lg bg-white flex flex-row justify-items-stretch ">
<TaskInfo id={tasks[0].id} output="Submit your answer" />
<Flex justify="center" ml="auto" gap={2}>
<SkipButton>Skip</SkipButton>
<SubmitButton onClick={() => submitResponse(tasks[0])} disabled={ranking.length === 0}>
Submit
</SubmitButton>
</Flex>
</section>
</main>
</>
);
};
export default RankUserReplies;
+10 -18
View File
@@ -1,4 +1,4 @@
import { Textarea } from "@chakra-ui/react";
import { Flex, Textarea } from "@chakra-ui/react";
import { QuestionMarkCircleIcon } from "@heroicons/react/20/solid";
import Head from "next/head";
import { useState } from "react";
@@ -9,9 +9,11 @@ import RatingRadioGroup from "src/components/RatingRadioGroup";
import fetcher from "src/lib/fetcher";
import poster from "src/lib/poster";
import { LoadingScreen } from "src/components/Loading/LoadingScreen";
import { TwoColumns } from "src/components/TwoColumns";
import { Button } from "src/components/Button";
import { LoadingScreen } from "@/components/Loading/LoadingScreen";
import { TaskInfo } from "src/components/TaskInfo/TaskInfo";
import { SkipButton } from "src/components/Buttons/Skip";
import { SubmitButton } from "src/components/Buttons/Submit";
const RateSummary = () => {
// Use an array of tasks that record the sequence of steps until a task is
@@ -91,22 +93,12 @@ const RateSummary = () => {
</TwoColumns>
<section className="mb-8 p-4 rounded-lg shadow-lg bg-white flex flex-row justify-items-stretch ">
<div className="grid grid-cols-[min-content_auto] gap-x-2 text-gray-700">
<b>Prompt</b>
<span>{tasks[0].id}</span>
<b>Output</b>
<span>Submit your answer</span>
</div>
<TaskInfo id={tasks[0].id} output="Submit your answer" />
<div className="flex justify-center ml-auto">
<Button className="mr-2 bg-indigo-100 text-indigo-700 hover:bg-indigo-200">Skip</Button>
<Button
onClick={() => submitResponse(tasks[0])}
className="bg-indigo-600 text-white shadow-sm hover:bg-indigo-700"
>
Submit
</Button>
</div>
<Flex justify="center" ml="auto" gap={2}>
<SkipButton>Skip</SkipButton>
<SubmitButton onClick={() => submitResponse(tasks[0])}>Submit</SubmitButton>
</Flex>
</section>
</main>
</>
@@ -1,7 +1,5 @@
import RankItem from "src/components/RankItem";
import { BarsArrowUpIcon, BarsArrowDownIcon } from "@heroicons/react/24/solid";
import Image from "next/image";
import { HiBarsArrowUp, HiBarsArrowDown } from "react-icons/hi2";
import { HiBarsArrowDown } from "react-icons/hi2";
const LeaderBoard = () => {
const PlaceHolderProps = { username: "test_user", score: 10 };
+1 -4
View File
@@ -14,10 +14,7 @@
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
"baseUrl": "."
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]