letta-nightly 0.5.4.dev20241125104219__tar.gz → 0.5.4.dev20241126104249__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of letta-nightly might be problematic. Click here for more details.

Files changed (226) hide show
  1. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/PKG-INFO +1 -1
  2. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/agent.py +6 -0
  3. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/cli/cli_config.py +1 -1
  4. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/client/client.py +72 -47
  5. letta_nightly-0.5.4.dev20241126104249/letta/orm/errors.py +14 -0
  6. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/orm/sqlalchemy_base.py +46 -7
  7. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/schemas/tool.py +25 -1
  8. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/rest_api/routers/v1/tools.py +35 -5
  9. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/services/tool_manager.py +5 -12
  10. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/pyproject.toml +1 -1
  11. letta_nightly-0.5.4.dev20241125104219/letta/orm/errors.py +0 -6
  12. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/LICENSE +0 -0
  13. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/README.md +0 -0
  14. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/__init__.py +0 -0
  15. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/__main__.py +0 -0
  16. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/agent_store/chroma.py +0 -0
  17. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/agent_store/db.py +0 -0
  18. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/agent_store/lancedb.py +0 -0
  19. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/agent_store/milvus.py +0 -0
  20. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/agent_store/qdrant.py +0 -0
  21. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/agent_store/storage.py +0 -0
  22. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/benchmark/benchmark.py +0 -0
  23. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/benchmark/constants.py +0 -0
  24. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/cli/cli.py +0 -0
  25. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/cli/cli_load.py +0 -0
  26. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/client/__init__.py +0 -0
  27. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/client/streaming.py +0 -0
  28. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/client/utils.py +0 -0
  29. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/config.py +0 -0
  30. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/constants.py +0 -0
  31. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/credentials.py +0 -0
  32. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/data_sources/connectors.py +0 -0
  33. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/data_sources/connectors_helper.py +0 -0
  34. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/embeddings.py +0 -0
  35. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/errors.py +0 -0
  36. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/functions/__init__.py +0 -0
  37. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/functions/function_sets/base.py +0 -0
  38. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/functions/function_sets/extras.py +0 -0
  39. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/functions/functions.py +0 -0
  40. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/functions/helpers.py +0 -0
  41. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/functions/schema_generator.py +0 -0
  42. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/helpers/__init__.py +0 -0
  43. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/helpers/tool_rule_solver.py +0 -0
  44. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/humans/__init__.py +0 -0
  45. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/humans/examples/basic.txt +0 -0
  46. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/humans/examples/cs_phd.txt +0 -0
  47. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/interface.py +0 -0
  48. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/llm_api/__init__.py +0 -0
  49. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/llm_api/anthropic.py +0 -0
  50. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/llm_api/azure_openai.py +0 -0
  51. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/llm_api/azure_openai_constants.py +0 -0
  52. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/llm_api/cohere.py +0 -0
  53. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/llm_api/google_ai.py +0 -0
  54. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/llm_api/helpers.py +0 -0
  55. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/llm_api/llm_api_tools.py +0 -0
  56. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/llm_api/mistral.py +0 -0
  57. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/llm_api/openai.py +0 -0
  58. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/README.md +0 -0
  59. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/__init__.py +0 -0
  60. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/chat_completion_proxy.py +0 -0
  61. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/constants.py +0 -0
  62. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/function_parser.py +0 -0
  63. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/grammars/__init__.py +0 -0
  64. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/grammars/gbnf_grammar_generator.py +0 -0
  65. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/grammars/json.gbnf +0 -0
  66. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/grammars/json_func_calls_with_inner_thoughts.gbnf +0 -0
  67. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/json_parser.py +0 -0
  68. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/koboldcpp/api.py +0 -0
  69. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/koboldcpp/settings.py +0 -0
  70. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/llamacpp/api.py +0 -0
  71. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/llamacpp/settings.py +0 -0
  72. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/llm_chat_completion_wrappers/__init__.py +0 -0
  73. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/llm_chat_completion_wrappers/airoboros.py +0 -0
  74. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/llm_chat_completion_wrappers/chatml.py +0 -0
  75. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/llm_chat_completion_wrappers/configurable_wrapper.py +0 -0
  76. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/llm_chat_completion_wrappers/dolphin.py +0 -0
  77. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/llm_chat_completion_wrappers/llama3.py +0 -0
  78. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/llm_chat_completion_wrappers/simple_summary_wrapper.py +0 -0
  79. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/llm_chat_completion_wrappers/wrapper_base.py +0 -0
  80. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/llm_chat_completion_wrappers/zephyr.py +0 -0
  81. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/lmstudio/api.py +0 -0
  82. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/lmstudio/settings.py +0 -0
  83. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/ollama/api.py +0 -0
  84. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/ollama/settings.py +0 -0
  85. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/settings/__init__.py +0 -0
  86. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/settings/deterministic_mirostat.py +0 -0
  87. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/settings/settings.py +0 -0
  88. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/settings/simple.py +0 -0
  89. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/utils.py +0 -0
  90. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/vllm/api.py +0 -0
  91. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/webui/api.py +0 -0
  92. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/webui/legacy_api.py +0 -0
  93. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/webui/legacy_settings.py +0 -0
  94. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/local_llm/webui/settings.py +0 -0
  95. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/log.py +0 -0
  96. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/main.py +0 -0
  97. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/memory.py +0 -0
  98. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/metadata.py +0 -0
  99. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/o1_agent.py +0 -0
  100. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/openai_backcompat/__init__.py +0 -0
  101. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/openai_backcompat/openai_object.py +0 -0
  102. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/orm/__all__.py +0 -0
  103. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/orm/__init__.py +0 -0
  104. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/orm/agents_tags.py +0 -0
  105. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/orm/base.py +0 -0
  106. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/orm/block.py +0 -0
  107. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/orm/blocks_agents.py +0 -0
  108. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/orm/enums.py +0 -0
  109. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/orm/file.py +0 -0
  110. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/orm/mixins.py +0 -0
  111. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/orm/organization.py +0 -0
  112. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/orm/sandbox_config.py +0 -0
  113. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/orm/source.py +0 -0
  114. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/orm/tool.py +0 -0
  115. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/orm/user.py +0 -0
  116. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/persistence_manager.py +0 -0
  117. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/personas/__init__.py +0 -0
  118. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/personas/examples/anna_pa.txt +0 -0
  119. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/personas/examples/google_search_persona.txt +0 -0
  120. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/personas/examples/memgpt_doc.txt +0 -0
  121. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/personas/examples/memgpt_starter.txt +0 -0
  122. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/personas/examples/o1_persona.txt +0 -0
  123. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/personas/examples/sam.txt +0 -0
  124. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/personas/examples/sam_pov.txt +0 -0
  125. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/personas/examples/sam_simple_pov_gpt35.txt +0 -0
  126. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/personas/examples/sqldb/test.db +0 -0
  127. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/prompts/__init__.py +0 -0
  128. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/prompts/gpt_summarize.py +0 -0
  129. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/prompts/gpt_system.py +0 -0
  130. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/prompts/system/memgpt_base.txt +0 -0
  131. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/prompts/system/memgpt_chat.txt +0 -0
  132. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/prompts/system/memgpt_chat_compressed.txt +0 -0
  133. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/prompts/system/memgpt_chat_fstring.txt +0 -0
  134. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/prompts/system/memgpt_doc.txt +0 -0
  135. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/prompts/system/memgpt_gpt35_extralong.txt +0 -0
  136. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/prompts/system/memgpt_intuitive_knowledge.txt +0 -0
  137. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/prompts/system/memgpt_modified_chat.txt +0 -0
  138. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/prompts/system/memgpt_modified_o1.txt +0 -0
  139. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/providers.py +0 -0
  140. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/pytest.ini +0 -0
  141. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/schemas/agent.py +0 -0
  142. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/schemas/agents_tags.py +0 -0
  143. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/schemas/api_key.py +0 -0
  144. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/schemas/block.py +0 -0
  145. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/schemas/blocks_agents.py +0 -0
  146. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/schemas/embedding_config.py +0 -0
  147. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/schemas/enums.py +0 -0
  148. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/schemas/file.py +0 -0
  149. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/schemas/health.py +0 -0
  150. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/schemas/job.py +0 -0
  151. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/schemas/letta_base.py +0 -0
  152. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/schemas/letta_message.py +0 -0
  153. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/schemas/letta_request.py +0 -0
  154. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/schemas/letta_response.py +0 -0
  155. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/schemas/llm_config.py +0 -0
  156. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/schemas/memory.py +0 -0
  157. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/schemas/message.py +0 -0
  158. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/schemas/openai/chat_completion_request.py +0 -0
  159. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/schemas/openai/chat_completion_response.py +0 -0
  160. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/schemas/openai/chat_completions.py +0 -0
  161. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/schemas/openai/embedding_response.py +0 -0
  162. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/schemas/openai/openai.py +0 -0
  163. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/schemas/organization.py +0 -0
  164. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/schemas/passage.py +0 -0
  165. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/schemas/sandbox_config.py +0 -0
  166. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/schemas/source.py +0 -0
  167. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/schemas/tool_rule.py +0 -0
  168. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/schemas/usage.py +0 -0
  169. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/schemas/user.py +0 -0
  170. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/__init__.py +0 -0
  171. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/constants.py +0 -0
  172. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/generate_openapi_schema.sh +0 -0
  173. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/rest_api/__init__.py +0 -0
  174. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/rest_api/app.py +0 -0
  175. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/rest_api/auth/__init__.py +0 -0
  176. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/rest_api/auth/index.py +0 -0
  177. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/rest_api/auth_token.py +0 -0
  178. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/rest_api/interface.py +0 -0
  179. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/rest_api/routers/__init__.py +0 -0
  180. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/rest_api/routers/openai/__init__.py +0 -0
  181. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/rest_api/routers/openai/assistants/__init__.py +0 -0
  182. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/rest_api/routers/openai/assistants/assistants.py +0 -0
  183. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/rest_api/routers/openai/assistants/schemas.py +0 -0
  184. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/rest_api/routers/openai/assistants/threads.py +0 -0
  185. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/rest_api/routers/openai/chat_completions/__init__.py +0 -0
  186. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/rest_api/routers/openai/chat_completions/chat_completions.py +0 -0
  187. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/rest_api/routers/v1/__init__.py +0 -0
  188. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/rest_api/routers/v1/agents.py +0 -0
  189. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/rest_api/routers/v1/blocks.py +0 -0
  190. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/rest_api/routers/v1/health.py +0 -0
  191. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/rest_api/routers/v1/jobs.py +0 -0
  192. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/rest_api/routers/v1/llms.py +0 -0
  193. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/rest_api/routers/v1/organizations.py +0 -0
  194. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/rest_api/routers/v1/sandbox_configs.py +0 -0
  195. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/rest_api/routers/v1/sources.py +0 -0
  196. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/rest_api/routers/v1/users.py +0 -0
  197. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/rest_api/static_files.py +0 -0
  198. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/rest_api/utils.py +0 -0
  199. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/server.py +0 -0
  200. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/startup.sh +0 -0
  201. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/static_files/assets/index-3ab03d5b.css +0 -0
  202. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/static_files/assets/index-9fa459a2.js +0 -0
  203. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/static_files/favicon.ico +0 -0
  204. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/static_files/index.html +0 -0
  205. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/static_files/memgpt_logo_transparent.png +0 -0
  206. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/utils.py +0 -0
  207. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/ws_api/__init__.py +0 -0
  208. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/ws_api/example_client.py +0 -0
  209. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/ws_api/interface.py +0 -0
  210. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/ws_api/protocol.py +0 -0
  211. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/server/ws_api/server.py +0 -0
  212. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/services/__init__.py +0 -0
  213. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/services/agents_tags_manager.py +0 -0
  214. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/services/block_manager.py +0 -0
  215. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/services/blocks_agents_manager.py +0 -0
  216. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/services/organization_manager.py +0 -0
  217. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/services/sandbox_config_manager.py +0 -0
  218. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/services/source_manager.py +0 -0
  219. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/services/tool_execution_sandbox.py +0 -0
  220. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/services/tool_sandbox_env/.gitkeep +0 -0
  221. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/services/user_manager.py +0 -0
  222. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/settings.py +0 -0
  223. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/streaming_interface.py +0 -0
  224. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/streaming_utils.py +0 -0
  225. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/system.py +0 -0
  226. {letta_nightly-0.5.4.dev20241125104219 → letta_nightly-0.5.4.dev20241126104249}/letta/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: letta-nightly
3
- Version: 0.5.4.dev20241125104219
3
+ Version: 0.5.4.dev20241126104249
4
4
  Summary: Create LLM agents with long-term memory and custom tools
5
5
  License: Apache License
6
6
  Author: Letta Team
@@ -1325,6 +1325,12 @@ class Agent(BaseAgent):
1325
1325
 
1326
1326
  def update_state(self) -> AgentState:
1327
1327
  message_ids = [msg.id for msg in self._messages]
1328
+
1329
+ # Assert that these are all strings
1330
+ if any(not isinstance(m_id, str) for m_id in message_ids):
1331
+ warnings.warn(f"Non-string message IDs found in agent state: {message_ids}")
1332
+ message_ids = [m_id for m_id in message_ids if isinstance(m_id, str)]
1333
+
1328
1334
  assert isinstance(self.memory, Memory), f"Memory is not a Memory object: {type(self.memory)}"
1329
1335
 
1330
1336
  # override any fields that may have been updated
@@ -136,7 +136,7 @@ def add_tool(
136
136
  func = eval(func_def.name)
137
137
 
138
138
  # 4. Add or update the tool
139
- tool = client.create_tool(func=func, name=name, tags=tags, update=update)
139
+ tool = client.create_or_update_tool(func=func, name=name, tags=tags, update=update)
140
140
  print(f"Tool {tool.name} added successfully")
141
141
 
142
142
 
@@ -211,6 +211,14 @@ class AbstractClient(object):
211
211
  ) -> Tool:
212
212
  raise NotImplementedError
213
213
 
214
+ def create_or_update_tool(
215
+ self,
216
+ func,
217
+ name: Optional[str] = None,
218
+ tags: Optional[List[str]] = None,
219
+ ) -> Tool:
220
+ raise NotImplementedError
221
+
214
222
  def update_tool(
215
223
  self,
216
224
  id: str,
@@ -532,7 +540,7 @@ class RESTClient(AbstractClient):
532
540
  # add memory tools
533
541
  memory_functions = get_memory_functions(memory)
534
542
  for func_name, func in memory_functions.items():
535
- tool = self.create_tool(func, name=func_name, tags=["memory", "letta-base"])
543
+ tool = self.create_or_update_tool(func, name=func_name, tags=["memory", "letta-base"])
536
544
  tool_names.append(tool.name)
537
545
 
538
546
  # check if default configs are provided
@@ -1440,18 +1448,39 @@ class RESTClient(AbstractClient):
1440
1448
  Returns:
1441
1449
  tool (Tool): The created tool.
1442
1450
  """
1451
+ source_code = parse_source_code(func)
1452
+ source_type = "python"
1443
1453
 
1444
- # TODO: check tool update code
1445
- # TODO: check if tool already exists
1454
+ # call server function
1455
+ request = ToolCreate(source_type=source_type, source_code=source_code, name=name, tags=tags)
1456
+ response = requests.post(f"{self.base_url}/{self.api_prefix}/tools", json=request.model_dump(), headers=self.headers)
1457
+ if response.status_code != 200:
1458
+ raise ValueError(f"Failed to create tool: {response.text}")
1459
+ return Tool(**response.json())
1446
1460
 
1447
- # TODO: how to load modules?
1448
- # parse source code/schema
1461
+ def create_or_update_tool(
1462
+ self,
1463
+ func: Callable,
1464
+ name: Optional[str] = None,
1465
+ tags: Optional[List[str]] = None,
1466
+ ) -> Tool:
1467
+ """
1468
+ Creates or updates a tool. This stores the source code of function on the server, so that the server can execute the function and generate an OpenAI JSON schemas for it when using with an agent.
1469
+
1470
+ Args:
1471
+ func (callable): The function to create a tool for.
1472
+ name: (str): Name of the tool (must be unique per-user.)
1473
+ tags (Optional[List[str]], optional): Tags for the tool. Defaults to None.
1474
+
1475
+ Returns:
1476
+ tool (Tool): The created tool.
1477
+ """
1449
1478
  source_code = parse_source_code(func)
1450
1479
  source_type = "python"
1451
1480
 
1452
1481
  # call server function
1453
1482
  request = ToolCreate(source_type=source_type, source_code=source_code, name=name, tags=tags)
1454
- response = requests.post(f"{self.base_url}/{self.api_prefix}/tools", json=request.model_dump(), headers=self.headers)
1483
+ response = requests.put(f"{self.base_url}/{self.api_prefix}/tools", json=request.model_dump(), headers=self.headers)
1455
1484
  if response.status_code != 200:
1456
1485
  raise ValueError(f"Failed to create tool: {response.text}")
1457
1486
  return Tool(**response.json())
@@ -1489,45 +1518,6 @@ class RESTClient(AbstractClient):
1489
1518
  raise ValueError(f"Failed to update tool: {response.text}")
1490
1519
  return Tool(**response.json())
1491
1520
 
1492
- # def create_tool(
1493
- # self,
1494
- # func,
1495
- # name: Optional[str] = None,
1496
- # update: Optional[bool] = True, # TODO: actually use this
1497
- # tags: Optional[List[str]] = None,
1498
- # ):
1499
- # """Create a tool
1500
-
1501
- # Args:
1502
- # func (callable): The function to create a tool for.
1503
- # tags (Optional[List[str]], optional): Tags for the tool. Defaults to None.
1504
- # update (bool, optional): Update the tool if it already exists. Defaults to True.
1505
-
1506
- # Returns:
1507
- # Tool object
1508
- # """
1509
-
1510
- # # TODO: check if tool already exists
1511
- # # TODO: how to load modules?
1512
- # # parse source code/schema
1513
- # source_code = parse_source_code(func)
1514
- # json_schema = generate_schema(func, name)
1515
- # source_type = "python"
1516
- # json_schema["name"]
1517
-
1518
- # # create data
1519
- # data = {"source_code": source_code, "source_type": source_type, "tags": tags, "json_schema": json_schema, "update": update}
1520
- # try:
1521
- # CreateToolRequest(**data) # validate data
1522
- # except Exception as e:
1523
- # raise ValueError(f"Failed to create tool: {e}, invalid input {data}")
1524
-
1525
- # # make REST request
1526
- # response = requests.post(f"{self.base_url}/{self.api_prefix}/tools", json=data, headers=self.headers)
1527
- # if response.status_code != 200:
1528
- # raise ValueError(f"Failed to create tool: {response.text}")
1529
- # return ToolModel(**response.json())
1530
-
1531
1521
  def list_tools(self, cursor: Optional[str] = None, limit: Optional[int] = 50) -> List[Tool]:
1532
1522
  """
1533
1523
  List available tools for the user.
@@ -1977,7 +1967,7 @@ class LocalClient(AbstractClient):
1977
1967
  # add memory tools
1978
1968
  memory_functions = get_memory_functions(memory)
1979
1969
  for func_name, func in memory_functions.items():
1980
- tool = self.create_tool(func, name=func_name, tags=["memory", "letta-base"])
1970
+ tool = self.create_or_update_tool(func, name=func_name, tags=["memory", "letta-base"])
1981
1971
  tool_names.append(tool.name)
1982
1972
 
1983
1973
  self.interface.clear()
@@ -2573,7 +2563,6 @@ class LocalClient(AbstractClient):
2573
2563
  tool_create = ToolCreate.from_composio(action=action)
2574
2564
  return self.server.tool_manager.create_or_update_tool(pydantic_tool=Tool(**tool_create.model_dump()), actor=self.user)
2575
2565
 
2576
- # TODO: Use the above function `add_tool` here as there is duplicate logic
2577
2566
  def create_tool(
2578
2567
  self,
2579
2568
  func,
@@ -2601,6 +2590,42 @@ class LocalClient(AbstractClient):
2601
2590
  if not tags:
2602
2591
  tags = []
2603
2592
 
2593
+ # call server function
2594
+ return self.server.tool_manager.create_tool(
2595
+ Tool(
2596
+ source_type=source_type,
2597
+ source_code=source_code,
2598
+ name=name,
2599
+ tags=tags,
2600
+ description=description,
2601
+ ),
2602
+ actor=self.user,
2603
+ )
2604
+
2605
+ def create_or_update_tool(
2606
+ self,
2607
+ func,
2608
+ name: Optional[str] = None,
2609
+ tags: Optional[List[str]] = None,
2610
+ description: Optional[str] = None,
2611
+ ) -> Tool:
2612
+ """
2613
+ Creates or updates a tool. This stores the source code of function on the server, so that the server can execute the function and generate an OpenAI JSON schemas for it when using with an agent.
2614
+
2615
+ Args:
2616
+ func (callable): The function to create a tool for.
2617
+ name: (str): Name of the tool (must be unique per-user.)
2618
+ tags (Optional[List[str]], optional): Tags for the tool. Defaults to None.
2619
+ description (str, optional): The description.
2620
+
2621
+ Returns:
2622
+ tool (Tool): The created tool.
2623
+ """
2624
+ source_code = parse_source_code(func)
2625
+ source_type = "python"
2626
+ if not tags:
2627
+ tags = []
2628
+
2604
2629
  # call server function
2605
2630
  return self.server.tool_manager.create_or_update_tool(
2606
2631
  Tool(
@@ -0,0 +1,14 @@
1
+ class NoResultFound(Exception):
2
+ """A record or records cannot be found given the provided search params"""
3
+
4
+
5
+ class MalformedIdError(Exception):
6
+ """An id not in the right format, most likely violating uuid4 format."""
7
+
8
+
9
+ class UniqueConstraintViolationError(ValueError):
10
+ """Custom exception for unique constraint violations."""
11
+
12
+
13
+ class ForeignKeyConstraintViolationError(ValueError):
14
+ """Custom exception for foreign key constraint violations."""
@@ -1,11 +1,16 @@
1
1
  from typing import TYPE_CHECKING, List, Literal, Optional, Type
2
2
 
3
3
  from sqlalchemy import String, select
4
+ from sqlalchemy.exc import DBAPIError
4
5
  from sqlalchemy.orm import Mapped, mapped_column
5
6
 
6
7
  from letta.log import get_logger
7
8
  from letta.orm.base import Base, CommonSqlalchemyMetaMixins
8
- from letta.orm.errors import NoResultFound
9
+ from letta.orm.errors import (
10
+ ForeignKeyConstraintViolationError,
11
+ NoResultFound,
12
+ UniqueConstraintViolationError,
13
+ )
9
14
 
10
15
  if TYPE_CHECKING:
11
16
  from pydantic import BaseModel
@@ -102,12 +107,14 @@ class SqlalchemyBase(CommonSqlalchemyMetaMixins, Base):
102
107
 
103
108
  if actor:
104
109
  self._set_created_and_updated_by_fields(actor.id)
105
-
106
- with db_session as session:
107
- session.add(self)
108
- session.commit()
109
- session.refresh(self)
110
- return self
110
+ try:
111
+ with db_session as session:
112
+ session.add(self)
113
+ session.commit()
114
+ session.refresh(self)
115
+ return self
116
+ except DBAPIError as e:
117
+ self._handle_dbapi_error(e)
111
118
 
112
119
  def delete(self, db_session: "Session", actor: Optional["User"] = None) -> Type["SqlalchemyBase"]:
113
120
  logger.debug(f"Soft deleting {self.__class__.__name__} with ID: {self.id} with actor={actor}")
@@ -168,6 +175,38 @@ class SqlalchemyBase(CommonSqlalchemyMetaMixins, Base):
168
175
  raise ValueError(f"object {actor} has no organization accessor")
169
176
  return query.where(cls.organization_id == org_id, cls.is_deleted == False)
170
177
 
178
+ @classmethod
179
+ def _handle_dbapi_error(cls, e: DBAPIError):
180
+ """Handle database errors and raise appropriate custom exceptions."""
181
+ orig = e.orig # Extract the original error from the DBAPIError
182
+ error_code = None
183
+
184
+ # For psycopg2
185
+ if hasattr(orig, "pgcode"):
186
+ error_code = orig.pgcode
187
+ # For pg8000
188
+ elif hasattr(orig, "args") and len(orig.args) > 0:
189
+ # The first argument contains the error details as a dictionary
190
+ err_dict = orig.args[0]
191
+ if isinstance(err_dict, dict):
192
+ error_code = err_dict.get("C") # 'C' is the error code field
193
+ logger.info(f"Extracted error_code: {error_code}")
194
+
195
+ # Handle unique constraint violations
196
+ if error_code == "23505":
197
+ raise UniqueConstraintViolationError(
198
+ f"A unique constraint was violated for {cls.__name__}. Check your input for duplicates: {e}"
199
+ ) from e
200
+
201
+ # Handle foreign key violations
202
+ if error_code == "23503":
203
+ raise ForeignKeyConstraintViolationError(
204
+ f"A foreign key constraint was violated for {cls.__name__}. Check your input for missing or invalid references: {e}"
205
+ ) from e
206
+
207
+ # Re-raise for other unhandled DBAPI errors
208
+ raise
209
+
171
210
  @property
172
211
  def __pydantic_model__(self) -> Type["BaseModel"]:
173
212
  raise NotImplementedError("Sqlalchemy models must declare a __pydantic_model__ property to be convertable.")
@@ -1,7 +1,8 @@
1
1
  from typing import Dict, List, Optional
2
2
 
3
- from pydantic import Field
3
+ from pydantic import Field, model_validator
4
4
 
5
+ from letta.functions.functions import derive_openai_json_schema
5
6
  from letta.functions.helpers import (
6
7
  generate_composio_tool_wrapper,
7
8
  generate_langchain_tool_wrapper,
@@ -44,6 +45,29 @@ class Tool(BaseTool):
44
45
  created_by_id: Optional[str] = Field(None, description="The id of the user that made this Tool.")
45
46
  last_updated_by_id: Optional[str] = Field(None, description="The id of the user that made this Tool.")
46
47
 
48
+ @model_validator(mode="after")
49
+ def populate_missing_fields(self):
50
+ """
51
+ Populate missing fields: name, description, and json_schema.
52
+ """
53
+ # Derive JSON schema if not provided
54
+ if not self.json_schema:
55
+ self.json_schema = derive_openai_json_schema(source_code=self.source_code)
56
+
57
+ # Derive name from the JSON schema if not provided
58
+ if not self.name:
59
+ # TODO: This in theory could error, but name should always be on json_schema
60
+ # TODO: Make JSON schema a typed pydantic object
61
+ self.name = self.json_schema.get("name")
62
+
63
+ # Derive description from the JSON schema if not provided
64
+ if not self.description:
65
+ # TODO: This in theory could error, but description should always be on json_schema
66
+ # TODO: Make JSON schema a typed pydantic object
67
+ self.description = self.json_schema.get("description")
68
+
69
+ return self
70
+
47
71
  def to_dict(self):
48
72
  """
49
73
  Convert tool into OpenAI representation.
@@ -2,6 +2,7 @@ from typing import List, Optional
2
2
 
3
3
  from fastapi import APIRouter, Body, Depends, Header, HTTPException
4
4
 
5
+ from letta.orm.errors import UniqueConstraintViolationError
5
6
  from letta.schemas.tool import Tool, ToolCreate, ToolUpdate
6
7
  from letta.server.rest_api.utils import get_letta_server
7
8
  from letta.server.server import SyncServer
@@ -83,12 +84,41 @@ def create_tool(
83
84
  """
84
85
  Create a new tool
85
86
  """
86
- # Derive user and org id from actor
87
- actor = server.get_user_or_default(user_id=user_id)
87
+ try:
88
+ actor = server.get_user_or_default(user_id=user_id)
89
+ tool = Tool(**request.model_dump())
90
+ return server.tool_manager.create_tool(pydantic_tool=tool, actor=actor)
91
+ except UniqueConstraintViolationError as e:
92
+ # Log or print the full exception here for debugging
93
+ print(f"Error occurred: {e}")
94
+ raise HTTPException(status_code=409, detail=str(e))
95
+ except Exception as e:
96
+ # Catch other unexpected errors and raise an internal server error
97
+ print(f"Unexpected error occurred: {e}")
98
+ raise HTTPException(status_code=500, detail=f"An unexpected error occurred: {str(e)}")
88
99
 
89
- # Send request to create the tool
90
- tool = Tool(**request.model_dump())
91
- return server.tool_manager.create_or_update_tool(pydantic_tool=tool, actor=actor)
100
+
101
+ @router.put("/", response_model=Tool, operation_id="upsert_tool")
102
+ def upsert_tool(
103
+ request: ToolCreate = Body(...),
104
+ server: SyncServer = Depends(get_letta_server),
105
+ user_id: Optional[str] = Header(None, alias="user_id"),
106
+ ):
107
+ """
108
+ Create or update a tool
109
+ """
110
+ try:
111
+ actor = server.get_user_or_default(user_id=user_id)
112
+ tool = server.tool_manager.create_or_update_tool(pydantic_tool=Tool(**request.model_dump()), actor=actor)
113
+ return tool
114
+ except UniqueConstraintViolationError as e:
115
+ # Log the error and raise a conflict exception
116
+ print(f"Unique constraint violation occurred: {e}")
117
+ raise HTTPException(status_code=409, detail=str(e))
118
+ except Exception as e:
119
+ # Catch other unexpected errors and raise an internal server error
120
+ print(f"Unexpected error occurred: {e}")
121
+ raise HTTPException(status_code=500, detail=f"An unexpected error occurred: {str(e)}")
92
122
 
93
123
 
94
124
  @router.patch("/{tool_id}", response_model=Tool, operation_id="update_tool")
@@ -35,9 +35,7 @@ class ToolManager:
35
35
  def create_or_update_tool(self, pydantic_tool: PydanticTool, actor: PydanticUser) -> PydanticTool:
36
36
  """Create a new tool based on the ToolCreate schema."""
37
37
  # Derive json_schema
38
- derived_json_schema = pydantic_tool.json_schema or derive_openai_json_schema(source_code=pydantic_tool.source_code)
39
- derived_name = pydantic_tool.name or derived_json_schema["name"]
40
- tool = self.get_tool_by_name(tool_name=derived_name, actor=actor)
38
+ tool = self.get_tool_by_name(tool_name=pydantic_tool.name, actor=actor)
41
39
  if tool:
42
40
  # Put to dict and remove fields that should not be reset
43
41
  update_data = pydantic_tool.model_dump(exclude={"module"}, exclude_unset=True, exclude_none=True)
@@ -52,8 +50,6 @@ class ToolManager:
52
50
  f"`create_or_update_tool` was called with user_id={actor.id}, organization_id={actor.organization_id}, name={pydantic_tool.name}, but found existing tool with nothing to update."
53
51
  )
54
52
  else:
55
- pydantic_tool.json_schema = derived_json_schema
56
- pydantic_tool.name = derived_name
57
53
  tool = self.create_tool(pydantic_tool, actor=actor)
58
54
 
59
55
  return tool
@@ -61,18 +57,15 @@ class ToolManager:
61
57
  @enforce_types
62
58
  def create_tool(self, pydantic_tool: PydanticTool, actor: PydanticUser) -> PydanticTool:
63
59
  """Create a new tool based on the ToolCreate schema."""
64
- # Create the tool
65
60
  with self.session_maker() as session:
66
61
  # Set the organization id at the ORM layer
67
62
  pydantic_tool.organization_id = actor.organization_id
63
+ # Auto-generate description if not provided
64
+ if pydantic_tool.description is None:
65
+ pydantic_tool.description = pydantic_tool.json_schema.get("description", None)
68
66
  tool_data = pydantic_tool.model_dump()
69
67
  tool = ToolModel(**tool_data)
70
- # The description is most likely auto-generated via the json_schema,
71
- # so copy it over into the top-level description field
72
- if tool.description is None:
73
- tool.description = tool.json_schema.get("description", None)
74
- tool.create(session, actor=actor)
75
-
68
+ tool.create(session, actor=actor) # Re-raise other database-related errors
76
69
  return tool.to_pydantic()
77
70
 
78
71
  @enforce_types
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "letta-nightly"
3
- version = "0.5.4.dev20241125104219"
3
+ version = "0.5.4.dev20241126104249"
4
4
  packages = [
5
5
  {include = "letta"}
6
6
  ]
@@ -1,6 +0,0 @@
1
- class NoResultFound(Exception):
2
- """A record or records cannot be found given the provided search params"""
3
-
4
-
5
- class MalformedIdError(Exception):
6
- """An id not in the right format, most likely violating uuid4 format."""