mirror of
https://github.com/OpenHands/OpenHands.git
synced 2025-12-26 05:48:36 +08:00
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:
parent
6aec3d789e
commit
6596d5c799
@ -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),
|
||||
},
|
||||
);
|
||||
@ -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),
|
||||
};
|
||||
|
||||
|
||||
19
frontend/src/services/feedbackService.ts
Normal file
19
frontend/src/services/feedbackService.ts
Normal 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),
|
||||
});
|
||||
}
|
||||
31
opendevin/server/data_models/feedback.py
Normal file
31
opendevin/server/data_models/feedback.py
Normal 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}')
|
||||
@ -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):
|
||||
"""
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user