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

fix: remove problematic redundant uuid conversion and add api input param validations to api server #2051

Merged

Conversation

jonathanykh
Copy link
Contributor

@jonathanykh jonathanykh commented Jan 9, 2025

Relates to

N/A - this is an issue and will be described below in the Background section

Risks

Low - This is a bug fix and a defensive programming change that adds more robust input validation.

Background

What does this PR do?

  1. Removes incorrect usage of stringToUuid for API parameters that should already be in UUID format
  2. Adds proper UUID validation for API input parameters (agentId, roomId)
  3. Implements consistent error handling with appropriate HTTP status codes and messages
  4. Centralizes UUID validation logic in a reusable function

What kind of change is this?

Bug fixes (non-breaking change which fixes an issue) and Improvements (misc. changes to existing features)

Why are we doing this? Any context or related work?

We're making these changes to address two issues:

  1. Bug Fix: There was a bug in the /agents/:agentId/:roomId/memories endpoint at client-direct where stringToUuid() was being incorrectly applied to the roomId parameter. This caused:
  • The original valid UUID to be unnecessarily converted
  • Generation of a new, different UUID
  • Failed memory retrievals due to UUID mismatch

image
To further show case the problem, orginal room ID: ad22e47a-3fd0-05dc-8791-8fba9e475378 was altered by stringToUuid() to 8e9b5550-ca28-0f3c-a1f4-f13c2cdf3dca, leading to memories failed to be fetched by runtime.messageManager.getMemories.

Response:

{
  "agentId": "b850bc30-45f8-0041-a00a-83df46d8555d",
  "roomId": "8e9b5550-ca28-0f3c-a1f4-f13c2cdf3dca",
  "memories": []
}
  1. Defensive Programming: The API server was not validating UUID parameters, which led to:
  • No validation of input format
  • Silent failures when invalid UUIDs were provided

This PR implements proper input validation and error handling, making the API more robust and developer-friendly.

Documentation changes needed?

My changes do not require a change to the project documentation.

Testing

Where should a reviewer start?

  1. Review the UUID type validation function introduced at packages/core/src/uuid.ts
  2. Review the new validateUUIDParams function in packages/client-direct/src/api.ts
  3. Check the implementation across all API endpoints that use agentId or roomId

Detailed testing steps

  1. Test /agents/:agentId/:roomId/memories endpoint:
  • With valid UUIDs - should work normally
  • With invalid agentId - should return 400 with appropriate error message
  • With invalid roomId - should return 400 with appropriate error message
  1. Test other endpoints with agentId parameter:
  • /agents/:agentId
  • /agents/:agentId/set
  • /agents/:agentId/channels
  1. Verify error messages from 1. are clear and helpful.

Discord username

jonathanykh

@jonathanykh
Copy link
Contributor Author

Regarding testing, there is this simple Python script that I can provide to facilitate calls to the API server (normally at localhost:3000) and test the results of different inputs (e.g. invalid UUID):

import requests
import json
from typing import Dict, Any

BASE_URL = "http://localhost:3000"


def print_menu():
    print("\n=== Eliza API Client ===")
    print("1. Welcome message")
    print("2. Hello world")
    print("3. List all agents")
    print("4. Get agent details")
    print("5. Set agent character")
    print("6. Get agent's Discord channels")
    print("7. Get agent's memories")
    print("8. Exit")
    return input("Choose an option (1-8): ")


def pretty_print_response(response: Dict[str, Any]):
    print("\nResponse:")
    print(json.dumps(response, indent=2))


def get_welcome():
    response = requests.get(f"{BASE_URL}/")
    return response.text


def get_hello():
    response = requests.get(f"{BASE_URL}/hello")
    return response.json()


def list_agents():
    response = requests.get(f"{BASE_URL}/agents")
    return response.json()


def get_agent_details():
    agent_id = input("Enter agent ID: ")
    response = requests.get(f"{BASE_URL}/agents/{agent_id}")
    return response.json()


def set_agent_character():
    agent_id = input("Enter agent ID: ")
    print("Enter character configuration (JSON format):")
    character_json = input()
    try:
        character_data = json.loads(character_json)
        response = requests.post(
            f"{BASE_URL}/agents/{agent_id}/set", json=character_data
        )
        return response.json()
    except json.JSONDecodeError:
        return {"error": "Invalid JSON format"}


def get_agent_channels():
    agent_id = input("Enter agent ID: ")
    response = requests.get(f"{BASE_URL}/agents/{agent_id}/channels")
    return response.json()


def get_agent_memories():
    agent_id = input("Enter agent ID: ")
    room_id = input("Enter room ID: ")
    response = requests.get(f"{BASE_URL}/agents/{agent_id}/{room_id}/memories")
    return response.json()


def main():
    while True:
        choice = print_menu()

        try:
            if choice == "1":
                result = get_welcome()
                print("\nResponse:", result)

            elif choice == "2":
                result = get_hello()
                pretty_print_response(result)

            elif choice == "3":
                result = list_agents()
                pretty_print_response(result)

            elif choice == "4":
                result = get_agent_details()
                pretty_print_response(result)

            elif choice == "5":
                result = set_agent_character()
                pretty_print_response(result)

            elif choice == "6":
                result = get_agent_channels()
                pretty_print_response(result)

            elif choice == "7":
                result = get_agent_memories()
                pretty_print_response(result)

            elif choice == "8":
                print("Goodbye!")
                break

            else:
                print("Invalid option, please try again")

        except requests.exceptions.RequestException as e:
            print(f"\nError making request: {e}")
        except Exception as e:
            print(f"\nUnexpected error: {e}")


if __name__ == "__main__":
    main()

@tcm390
Copy link
Collaborator

tcm390 commented Jan 11, 2025

Hello @jonathanykh could you update pnpm-lock.yaml

@jonathanykh jonathanykh force-pushed the fix/remove-redundant-uuid-conversion branch from 543121f to d71bad2 Compare January 11, 2025 09:57
@jonathanykh jonathanykh force-pushed the fix/remove-redundant-uuid-conversion branch from 2e43930 to 77f0867 Compare January 11, 2025 10:30
@jonathanykh
Copy link
Contributor Author

Thanks @tcm390, I have updated the pnpm-lock.yaml, please take a look! :)

@odilitime odilitime merged commit aac570b into elizaOS:develop Jan 12, 2025
6 checks passed
mgunnin added a commit to mgunnin/eliza-agent that referenced this pull request Jan 12, 2025
* main: (704 commits)
  bump version (elizaOS#2193)
  feat(security): Implement comprehensive file upload security measures - Add FileSecurityValidator, file type restrictions, size limits, path traversal prevention, enhanced logging and security documentation (elizaOS#1753) (elizaOS#1806)
  fix(client-twitter): clean up mention deduplication (elizaOS#2185)
  fix postgres adapter migration extension creation which already exists at this point (elizaOS#2188)
  Update types.ts
  fix json format typo
  fix quai deps
  fix path
  Add Persian README File
  chore: lint and fix pass on develop (elizaOS#2180)
  bump version to 0,1,8
  bump
  clean up unused var in catch
  comment out unused AkashMessage interface
  bump eslint so it doesn't crash
  remove duplicate TOGETHER in case, lint/unused var
  convert imageDescriptionsArray from let to const per lint
  fix: Koloxarto/fix ragknowledge for postgres (elizaOS#2153)
  fix: fix the chat stuck in infinite loop (elizaOS#1755)
  fix: remove problematic redundant uuid conversion and add api input param validations to api server (elizaOS#2051)
  ...
0xpi-ai pushed a commit to 0xpi-ai/NayariAI that referenced this pull request Jan 15, 2025
…aram validations to api server (elizaOS#2051)

* fix: remove problematic redundant uuid conversion and add api input param validations to api server

* style: use object property shorthand for roomId

* chore: update pnpm-lock.yaml

---------

Co-authored-by: Monil Patel <[email protected]>
Co-authored-by: Odilitime <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants