Fix: Feedback should be sent through the backend to avoid CORS issues (#2046)

* Fix: Feedback should be sent through the backend to avoid CORS issues

* Update

* Fix merge error

* Revert unnecessary change

* Lint

* Moved to services

* Fixed bugs

---------

Co-authored-by: OpenDevin <opendevin@opendevin.ai>
This commit is contained in:
Graham Neubig 2024-05-31 15:00:09 -04:00 committed by GitHub
parent 6aec3d789e
commit 6596d5c799
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 80 additions and 20 deletions

View File

@ -1,19 +0,0 @@
export interface FeedbackData {
email: string;
token: string;
feedback: "positive" | "negative";
trajectory: unknown[];
}
export const sendFeedback = async (data: FeedbackData) =>
fetch(
"https://kttkfkoju5.execute-api.us-east-2.amazonaws.com/od-share-trajectory",
{
method: "POST",
mode: "no-cors",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
},
);

View File

@ -17,8 +17,8 @@ import { useScrollToBottom } from "#/hooks/useScrollToBottom";
import Session from "#/services/session";
import { getToken } from "#/services/auth";
import toast from "#/utils/toast";
import { FeedbackData, sendFeedback } from "#/api";
import { removeApiKey } from "#/utils/utils";
import { FeedbackData, sendFeedback } from "#/services/feedbackService";
interface ScrollButtonProps {
onClick: () => void;
@ -57,10 +57,13 @@ function ChatInterface() {
const [feedbackLoading, setFeedbackLoading] = React.useState(false);
const shareFeedback = async (feedback: "positive" | "negative") => {
// TODO: implement email and permissions
// https://github.com/OpenDevin/OpenDevin/issues/2033
const data: FeedbackData = {
email: "NOT_PROVIDED",
token: getToken(),
feedback,
permissions: "private",
trajectory: removeApiKey(Session._history),
};

View File

@ -0,0 +1,19 @@
import { request } from "./api";
export interface FeedbackData {
email: string;
token: string;
feedback: "positive" | "negative";
permissions: "public" | "private";
trajectory: unknown[];
}
export async function sendFeedback(data: FeedbackData) {
await request("/api/submit-feedback", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
});
}

View File

@ -0,0 +1,31 @@
from typing import Any, Literal
import requests
from pydantic import BaseModel
from opendevin.core.logger import opendevin_logger as logger
class FeedbackDataModel(BaseModel):
email: str
token: str
feedback: Literal['positive', 'negative']
permissions: Literal['public', 'private']
trajectory: list[dict[str, Any]]
FEEDBACK_URL = (
'https://kttkfkoju5.execute-api.us-east-2.amazonaws.com/od-share-trajectory'
)
def store_feedback(feedback: FeedbackDataModel):
logger.info(f'Got feedback: {feedback.model_dump_json()}')
response = requests.post(
FEEDBACK_URL,
headers={'Content-Type': 'application/json'},
json=feedback.model_dump(),
)
logger.info(f'Stored feedback: {response.status_code} {response.text}')
if response.status_code != 200:
raise ValueError(f'Failed to store feedback: {response.text}')

View File

@ -1,6 +1,8 @@
import uuid
import warnings
from opendevin.server.data_models.feedback import FeedbackDataModel, store_feedback
with warnings.catch_warnings():
warnings.simplefilter('ignore')
import litellm
@ -279,6 +281,30 @@ async def upload_file(request: Request, files: list[UploadFile]):
return {'message': 'Files uploaded successfully', 'file_count': len(files)}
@app.post('/api/submit-feedback')
async def submit_feedback(request: Request, feedback: FeedbackDataModel):
"""
Upload files to the workspace.
To upload files:
```sh
curl -X POST -F "email=test@example.com" -F "token=abc" -F "feedback=positive" -F "permissions=private" -F "trajectory={}" http://localhost:3000/api/submit-feedback
```
"""
# Assuming the storage service is already configured in the backend
# and there is a function to handle the storage.
try:
store_feedback(feedback)
return JSONResponse(
status_code=200, content={'message': 'Feedback submitted successfully'}
)
except Exception as e:
logger.error(f'Error submitting feedback: {e}')
return JSONResponse(
status_code=500, content={'error': 'Failed to submit feedback'}
)
@app.get('/api/root_task')
def get_root_task(request: Request):
"""