Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] Fix 500 error in /hivechat/response endpoint - Primary key conflict in message creation #2210

Closed
5 tasks
humansinstitute opened this issue Dec 17, 2024 · 7 comments · Fixed by #2213
Closed
5 tasks
Assignees
Labels
bounties bug Something isn't working

Comments

@humansinstitute
Copy link
Contributor

Context

The /hivechat/response endpoint is currently returning 500 errors when processing responses from Stakwork. Investigation shows this is due to incorrect message ID handling in the response processing logic.

Current Behavior

  • The endpoint reuses the original message ID (the message being responded to) as the ID for the new assistant message
  • This causes a primary key conflict in the database since the ID already exists
  • Results in 500 Internal Server Error responses

Required Changes

  1. Modify the ProcessChatResponse handler in handlers/chat.go:
  • Generate a new unique ID for each assistant message using xid.New().String()
  • Keep the original messageId in the request structure for reference only
  • Ensure new messages are created with proper assistant/agent attributes
message := &db.ChatMessage{
    ID:        xid.New().String(),  // Generate new ID here
    ChatID:    request.ChatID,
    Message:   request.Response,
    Role:      "assistant",
    Timestamp: time.Now(),
    Status:    "sent",
    Source:    "agent",
}

Testing

  1. Verify successful message creation with unique IDs
  2. Confirm chat history maintains proper conversation flow
  3. Check WebSocket notifications still work correctly
  4. Test with multiple rapid responses to ensure no race conditions

Related Code

  • Primary handler: handlers/chat.go
  • Affected endpoint: /hivechat/response
  • Database model: ChatMessage struct

Additional Context
The messageId from Stakwork's response should be treated as a reference to the original message being responded to, not as the ID for the new message.

  • When receiving a response from Stakwork, the system generates a new unique message ID instead of reusing the original messageId
  • New assistant messages are correctly stored in the database with role="assistant" and source="agent"
  • The chat history shows a clear conversation flow between user messages and assistant responses
  • WebSocket notifications are successfully sent to the client with the newly created message details
  • The system handles concurrent responses without creating duplicate messages or database conflicts
@humansinstitute
Copy link
Contributor Author

@MahtabBukhari as discussed

@humansinstitute humansinstitute added bug Something isn't working bounties labels Dec 17, 2024
@MahtabBukhari
Copy link
Contributor

@humansinstitute assign

@humansinstitute
Copy link
Contributor Author

humansinstitute commented Dec 18, 2024

@MahtabBukhari -> Testing this morning, this isn't correctly processing the Chat ID as far as I can tell from Stakwork.

If we consider this screenshot of the look test, we can see that the chatId is returned as part of the 200 response.

Screenshot 2024-12-18 at 8 50 32 am

The messages aren't shown in the interface or returned from a Get Messages by Chat ID call (see network tab).

So my guess is that when these are processed we're not correctly setting the messages with the chat ID. Otherwise they would be returned on a page refresh (even if the websocket failed).

Screenshot 2024-12-18 at 8 55 04 am

Then when we check the stakwork output we see that we got a 200 message resposne, but that it doesn't include the chatId in the response.

Screenshot 2024-12-18 at 9 06 57 am
{
  "input": {
    "url": "https://people-test.sphinx.chat/hivechat/response",
    "method": "post",
    "headers": {
      "Content-Type": "application/json",
      "Accept": "application/json"
    },
    "request_params": {
      "value": {
        "chatId": "cth1kh4opisgms0ej8m0",
        "messageId": "cth1lm4opisgms0ej8ng",
        "response": "I apologize for the oversight. Given the context that this is a project with a TypeScript frontend and a Go backend, it seems like you might be asking about implementing or handling messaging features or improving message handling in this setup. Here's a more tailored response:\n\nIf you're looking to implement a messaging feature or handle messages between your TypeScript frontend and Go backend, here are some suggestions:\n\n1. **WebSockets**: For real-time messaging, consider using WebSockets. You can set up a WebSocket server in Go and communicate with it using a WebSocket client in TypeScript.\n\n2. **REST API**: If real-time isn't necessary, you can use a REST API for sending and receiving messages. Define endpoints in your Go backend to handle message operations and use HTTP requests from your TypeScript frontend.\n\n3. **gRPC**: For more efficient communication, especially if you're dealing with a lot of message exchanges, consider using gRPC with Protocol Buffers for defining service contracts and message structures.\n\n4. **Message Queues**: If you need to handle asynchronous messaging or decouple parts of your system, consider using a message queue system like RabbitMQ or Kafka.\n\n5. **Error Handling**: Ensure you have robust error handling on both the frontend and backend to deal with any issues that might arise in message transmission or processing.\n\nPlease let me know if you need more specific guidance on any of these options!",
        "sourceWebsocketId": null
      },
   },
}

Response:

      "response": {
        "success": true,
        "message": "Response processed successfully",
        "data": {
          "id": "cth1lo4opisgms0ej8o0",
          "chatId": "",
          "message": "",
          "role": "assistant",
          "timestamp": "2024-12-18T00:44:16.360524182Z",
          "contextTags": null,
          "status": "sent",
          "source": "agent"
        }
      },

@MahtabBukhari
Copy link
Contributor

@MahtabBukhari -> Testing this morning, this isn't correctly processing the Chat ID as far as I can tell from Stakwork.

If we consider this screenshot of the look test, we can see that the chatId is returned as part of the 200 response.

Screenshot 2024-12-18 at 8 50 32 am

The messages aren't shown in the interface or returned from a Get Messages by Chat ID call (see network tab)

Screenshot 2024-12-18 at 8 55 04 am

Then when we check the stakwork output we see that we got a 200 message resposne, but that it doesn't include the chatId in the response.

Screenshot 2024-12-18 at 9 06 57 am
{
  "input": {
    "url": "https://people-test.sphinx.chat/hivechat/response",
    "method": "post",
    "headers": {
      "Content-Type": "application/json",
      "Accept": "application/json"
    },
    "request_params": {
      "value": {
        "chatId": "cth1kh4opisgms0ej8m0",
        "messageId": "cth1lm4opisgms0ej8ng",
        "response": "I apologize for the oversight. Given the context that this is a project with a TypeScript frontend and a Go backend, it seems like you might be asking about implementing or handling messaging features or improving message handling in this setup. Here's a more tailored response:\n\nIf you're looking to implement a messaging feature or handle messages between your TypeScript frontend and Go backend, here are some suggestions:\n\n1. **WebSockets**: For real-time messaging, consider using WebSockets. You can set up a WebSocket server in Go and communicate with it using a WebSocket client in TypeScript.\n\n2. **REST API**: If real-time isn't necessary, you can use a REST API for sending and receiving messages. Define endpoints in your Go backend to handle message operations and use HTTP requests from your TypeScript frontend.\n\n3. **gRPC**: For more efficient communication, especially if you're dealing with a lot of message exchanges, consider using gRPC with Protocol Buffers for defining service contracts and message structures.\n\n4. **Message Queues**: If you need to handle asynchronous messaging or decouple parts of your system, consider using a message queue system like RabbitMQ or Kafka.\n\n5. **Error Handling**: Ensure you have robust error handling on both the frontend and backend to deal with any issues that might arise in message transmission or processing.\n\nPlease let me know if you need more specific guidance on any of these options!",
        "sourceWebsocketId": null
      },
   },
}

Response:

      "response": {
        "success": true,
        "message": "Response processed successfully",
        "data": {
          "id": "cth1lo4opisgms0ej8o0",
          "chatId": "",
          "message": "",
          "role": "assistant",
          "timestamp": "2024-12-18T00:44:16.360524182Z",
          "contextTags": null,
          "status": "sent",
          "source": "agent"
        }
      },

@humansinstitute let me check that one too
yes above screenshot is tested

@humansinstitute
Copy link
Contributor Author

humansinstitute commented Dec 18, 2024

Perhaps
ChatID: request.ChatID,

should be:
ChatID: request.chatId,

Given the return object?

@MahtabBukhari
Copy link
Contributor

MahtabBukhari commented Dec 18, 2024

Perhaps
ChatID: request.ChatID,

should be:
ChatID: request.chatId,

Given the return object?

issue is something else but let me check

@humansinstitute
Copy link
Contributor Author

humansinstitute commented Dec 18, 2024

Test Data

{
    "chatId": "cth73ssopisk0v5v8l30",
    "messageId": "cth74akopisk0v5v8l3g",
    "response": "I apologize for not addressing the context of a TypeScript frontend and Go backend in my initial response. Let's refine the explanation with that context in mind:\n\nWhen you send a message or request in a system with a TypeScript frontend and a Go backend, the following process typically occurs:\n\n1. **Frontend (TypeScript) Interaction**:\n   - You interact with the frontend application, which is likely a web application built with TypeScript. This could involve filling out a form or clicking a button to send a message.\n\n2. **HTTP Request**:\n   - The frontend uses HTTP (or WebSockets, if it's a real-time application) to send the data to the backend server. The data is often formatted as JSON.\n\n3. **Backend (Go) Processing**:\n   - The Go backend receives the HTTP request. The server, built with Go, processes the incoming request using a web framework or HTTP library. It will parse the JSON payload and perform any necessary logic, such as validating the data, storing it in a database, or triggering other business processes.\n\n4. **Response**:\n   - After processing the request, the Go backend typically sends a response back to the TypeScript frontend. This response could include a success message, error information, or data requested by the frontend.\n\n5. **Frontend Handling**:\n   - The TypeScript frontend receives the response and updates the UI accordingly. This might involve displaying a confirmation message, updating the view with new data, or handling any errors that occurred.\n\nThis is a general overview, and the specifics can vary based on the application's architecture and the nature of the message or request being sent. If you have more specific details about the functionality or flow you are concerned with, feel free to share them for a more precise explanation.",
    "sourceWebsocketId": "LP76MNPTKLZJALVHOSBFUGKU733V75EJEHHYECDN"
}

Other potential

"value":  {
    "chatId": "cth73ssopisk0v5v8l30",
    "messageId": "cth74akopisk0v5v8l3g",
    "response": "I apologize for not addressing the context of a TypeScript frontend and Go backend in my initial response. Let's refine the explanation with that context in mind:\n\nWhen you send a message or request in a system with a TypeScript frontend and a Go backend, the following process typically occurs:\n\n1. **Frontend (TypeScript) Interaction**:\n   - You interact with the frontend application, which is likely a web application built with TypeScript. This could involve filling out a form or clicking a button to send a message.\n\n2. **HTTP Request**:\n   - The frontend uses HTTP (or WebSockets, if it's a real-time application) to send the data to the backend server. The data is often formatted as JSON.\n\n3. **Backend (Go) Processing**:\n   - The Go backend receives the HTTP request. The server, built with Go, processes the incoming request using a web framework or HTTP library. It will parse the JSON payload and perform any necessary logic, such as validating the data, storing it in a database, or triggering other business processes.\n\n4. **Response**:\n   - After processing the request, the Go backend typically sends a response back to the TypeScript frontend. This response could include a success message, error information, or data requested by the frontend.\n\n5. **Frontend Handling**:\n   - The TypeScript frontend receives the response and updates the UI accordingly. This might involve displaying a confirmation message, updating the view with new data, or handling any errors that occurred.\n\nThis is a general overview, and the specifics can vary based on the application's architecture and the nature of the message or request being sent. If you have more specific details about the functionality or flow you are concerned with, feel free to share them for a more precise explanation.",
    "sourceWebsocketId": "LP76MNPTKLZJALVHOSBFUGKU733V75EJEHHYECDN"
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bounties bug Something isn't working
Projects
None yet
2 participants