letta-nightly 0.6.8.dev20250110190527__tar.gz → 0.6.8.dev20250111030335__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 (234) hide show
  1. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/PKG-INFO +1 -1
  2. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/agent.py +29 -21
  3. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/constants.py +4 -0
  4. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/functions/functions.py +65 -0
  5. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/llm_api/google_ai.py +78 -76
  6. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/orm/agent.py +2 -2
  7. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/orm/base.py +10 -0
  8. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/orm/provider.py +1 -1
  9. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/orm/sqlalchemy_base.py +9 -3
  10. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/orm/tool.py +7 -2
  11. {letta_nightly-0.6.8.dev20250110190527/letta → letta_nightly-0.6.8.dev20250111030335/letta/schemas}/providers.py +8 -3
  12. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/schemas/tool.py +21 -9
  13. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/rest_api/app.py +0 -4
  14. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/rest_api/interface.py +0 -4
  15. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/rest_api/routers/v1/__init__.py +12 -1
  16. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/rest_api/routers/v1/providers.py +13 -12
  17. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/server.py +13 -13
  18. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/services/provider_manager.py +11 -4
  19. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/services/sandbox_config_manager.py +2 -2
  20. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/services/tool_execution_sandbox.py +3 -2
  21. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/services/tool_manager.py +13 -9
  22. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/settings.py +7 -1
  23. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/pyproject.toml +1 -1
  24. letta_nightly-0.6.8.dev20250110190527/letta/services/tool_sandbox_env/.gitkeep +0 -0
  25. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/LICENSE +0 -0
  26. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/README.md +0 -0
  27. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/__init__.py +0 -0
  28. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/__main__.py +0 -0
  29. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/benchmark/benchmark.py +0 -0
  30. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/benchmark/constants.py +0 -0
  31. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/chat_only_agent.py +0 -0
  32. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/cli/cli.py +0 -0
  33. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/cli/cli_config.py +0 -0
  34. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/cli/cli_load.py +0 -0
  35. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/client/__init__.py +0 -0
  36. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/client/client.py +0 -0
  37. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/client/streaming.py +0 -0
  38. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/client/utils.py +0 -0
  39. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/config.py +0 -0
  40. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/credentials.py +0 -0
  41. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/data_sources/connectors.py +0 -0
  42. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/data_sources/connectors_helper.py +0 -0
  43. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/embeddings.py +0 -0
  44. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/errors.py +0 -0
  45. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/functions/__init__.py +0 -0
  46. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/functions/function_sets/base.py +0 -0
  47. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/functions/function_sets/extras.py +0 -0
  48. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/functions/helpers.py +0 -0
  49. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/functions/schema_generator.py +0 -0
  50. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/helpers/__init__.py +0 -0
  51. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/helpers/tool_rule_solver.py +0 -0
  52. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/humans/__init__.py +0 -0
  53. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/humans/examples/basic.txt +0 -0
  54. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/humans/examples/cs_phd.txt +0 -0
  55. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/interface.py +0 -0
  56. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/llm_api/__init__.py +0 -0
  57. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/llm_api/anthropic.py +0 -0
  58. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/llm_api/azure_openai.py +0 -0
  59. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/llm_api/azure_openai_constants.py +0 -0
  60. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/llm_api/cohere.py +0 -0
  61. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/llm_api/helpers.py +0 -0
  62. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/llm_api/llm_api_tools.py +0 -0
  63. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/llm_api/mistral.py +0 -0
  64. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/llm_api/openai.py +0 -0
  65. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/README.md +0 -0
  66. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/__init__.py +0 -0
  67. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/chat_completion_proxy.py +0 -0
  68. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/constants.py +0 -0
  69. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/function_parser.py +0 -0
  70. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/grammars/__init__.py +0 -0
  71. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/grammars/gbnf_grammar_generator.py +0 -0
  72. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/grammars/json.gbnf +0 -0
  73. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/grammars/json_func_calls_with_inner_thoughts.gbnf +0 -0
  74. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/json_parser.py +0 -0
  75. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/koboldcpp/api.py +0 -0
  76. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/koboldcpp/settings.py +0 -0
  77. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/llamacpp/api.py +0 -0
  78. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/llamacpp/settings.py +0 -0
  79. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/llm_chat_completion_wrappers/__init__.py +0 -0
  80. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/llm_chat_completion_wrappers/airoboros.py +0 -0
  81. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/llm_chat_completion_wrappers/chatml.py +0 -0
  82. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/llm_chat_completion_wrappers/configurable_wrapper.py +0 -0
  83. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/llm_chat_completion_wrappers/dolphin.py +0 -0
  84. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/llm_chat_completion_wrappers/llama3.py +0 -0
  85. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/llm_chat_completion_wrappers/simple_summary_wrapper.py +0 -0
  86. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/llm_chat_completion_wrappers/wrapper_base.py +0 -0
  87. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/llm_chat_completion_wrappers/zephyr.py +0 -0
  88. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/lmstudio/api.py +0 -0
  89. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/lmstudio/settings.py +0 -0
  90. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/ollama/api.py +0 -0
  91. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/ollama/settings.py +0 -0
  92. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/settings/__init__.py +0 -0
  93. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/settings/deterministic_mirostat.py +0 -0
  94. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/settings/settings.py +0 -0
  95. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/settings/simple.py +0 -0
  96. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/utils.py +0 -0
  97. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/vllm/api.py +0 -0
  98. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/webui/api.py +0 -0
  99. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/webui/legacy_api.py +0 -0
  100. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/webui/legacy_settings.py +0 -0
  101. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/local_llm/webui/settings.py +0 -0
  102. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/log.py +0 -0
  103. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/main.py +0 -0
  104. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/memory.py +0 -0
  105. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/offline_memory_agent.py +0 -0
  106. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/openai_backcompat/__init__.py +0 -0
  107. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/openai_backcompat/openai_object.py +0 -0
  108. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/orm/__all__.py +0 -0
  109. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/orm/__init__.py +0 -0
  110. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/orm/agents_tags.py +0 -0
  111. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/orm/block.py +0 -0
  112. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/orm/blocks_agents.py +0 -0
  113. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/orm/custom_columns.py +0 -0
  114. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/orm/enums.py +0 -0
  115. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/orm/errors.py +0 -0
  116. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/orm/file.py +0 -0
  117. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/orm/job.py +0 -0
  118. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/orm/message.py +0 -0
  119. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/orm/mixins.py +0 -0
  120. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/orm/organization.py +0 -0
  121. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/orm/passage.py +0 -0
  122. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/orm/sandbox_config.py +0 -0
  123. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/orm/source.py +0 -0
  124. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/orm/sources_agents.py +0 -0
  125. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/orm/sqlite_functions.py +0 -0
  126. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/orm/tools_agents.py +0 -0
  127. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/orm/user.py +0 -0
  128. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/personas/__init__.py +0 -0
  129. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/personas/examples/anna_pa.txt +0 -0
  130. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/personas/examples/google_search_persona.txt +0 -0
  131. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/personas/examples/memgpt_doc.txt +0 -0
  132. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/personas/examples/memgpt_starter.txt +0 -0
  133. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/personas/examples/o1_persona.txt +0 -0
  134. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/personas/examples/offline_memory_persona.txt +0 -0
  135. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/personas/examples/sam.txt +0 -0
  136. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/personas/examples/sam_pov.txt +0 -0
  137. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/personas/examples/sam_simple_pov_gpt35.txt +0 -0
  138. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/personas/examples/sqldb/test.db +0 -0
  139. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/prompts/__init__.py +0 -0
  140. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/prompts/gpt_summarize.py +0 -0
  141. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/prompts/gpt_system.py +0 -0
  142. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/prompts/system/memgpt_base.txt +0 -0
  143. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/prompts/system/memgpt_chat.txt +0 -0
  144. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/prompts/system/memgpt_chat_compressed.txt +0 -0
  145. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/prompts/system/memgpt_chat_fstring.txt +0 -0
  146. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/prompts/system/memgpt_convo_only.txt +0 -0
  147. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/prompts/system/memgpt_doc.txt +0 -0
  148. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/prompts/system/memgpt_gpt35_extralong.txt +0 -0
  149. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/prompts/system/memgpt_intuitive_knowledge.txt +0 -0
  150. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/prompts/system/memgpt_modified_chat.txt +0 -0
  151. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/prompts/system/memgpt_modified_o1.txt +0 -0
  152. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/prompts/system/memgpt_offline_memory.txt +0 -0
  153. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/prompts/system/memgpt_offline_memory_chat.txt +0 -0
  154. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/pytest.ini +0 -0
  155. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/schemas/agent.py +0 -0
  156. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/schemas/block.py +0 -0
  157. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/schemas/embedding_config.py +0 -0
  158. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/schemas/enums.py +0 -0
  159. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/schemas/environment_variables.py +0 -0
  160. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/schemas/file.py +0 -0
  161. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/schemas/health.py +0 -0
  162. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/schemas/job.py +0 -0
  163. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/schemas/letta_base.py +0 -0
  164. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/schemas/letta_message.py +0 -0
  165. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/schemas/letta_request.py +0 -0
  166. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/schemas/letta_response.py +0 -0
  167. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/schemas/llm_config.py +0 -0
  168. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/schemas/memory.py +0 -0
  169. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/schemas/message.py +0 -0
  170. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/schemas/openai/chat_completion_request.py +0 -0
  171. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/schemas/openai/chat_completion_response.py +0 -0
  172. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/schemas/openai/chat_completions.py +0 -0
  173. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/schemas/openai/embedding_response.py +0 -0
  174. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/schemas/openai/openai.py +0 -0
  175. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/schemas/organization.py +0 -0
  176. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/schemas/passage.py +0 -0
  177. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/schemas/sandbox_config.py +0 -0
  178. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/schemas/source.py +0 -0
  179. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/schemas/tool_rule.py +0 -0
  180. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/schemas/usage.py +0 -0
  181. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/schemas/user.py +0 -0
  182. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/__init__.py +0 -0
  183. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/constants.py +0 -0
  184. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/generate_openapi_schema.sh +0 -0
  185. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/rest_api/__init__.py +0 -0
  186. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/rest_api/auth/__init__.py +0 -0
  187. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/rest_api/auth/index.py +0 -0
  188. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/rest_api/auth_token.py +0 -0
  189. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/rest_api/routers/__init__.py +0 -0
  190. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/rest_api/routers/openai/__init__.py +0 -0
  191. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/rest_api/routers/openai/assistants/__init__.py +0 -0
  192. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/rest_api/routers/openai/assistants/assistants.py +0 -0
  193. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/rest_api/routers/openai/assistants/schemas.py +0 -0
  194. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/rest_api/routers/openai/chat_completions/__init__.py +0 -0
  195. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/rest_api/routers/openai/chat_completions/chat_completions.py +0 -0
  196. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/rest_api/routers/v1/agents.py +0 -0
  197. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/rest_api/routers/v1/blocks.py +0 -0
  198. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/rest_api/routers/v1/health.py +0 -0
  199. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/rest_api/routers/v1/jobs.py +0 -0
  200. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/rest_api/routers/v1/llms.py +0 -0
  201. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/rest_api/routers/v1/organizations.py +0 -0
  202. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/rest_api/routers/v1/sandbox_configs.py +0 -0
  203. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/rest_api/routers/v1/sources.py +0 -0
  204. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/rest_api/routers/v1/tools.py +0 -0
  205. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/rest_api/routers/v1/users.py +0 -0
  206. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/rest_api/static_files.py +0 -0
  207. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/rest_api/utils.py +0 -0
  208. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/startup.sh +0 -0
  209. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/static_files/assets/index-048c9598.js +0 -0
  210. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/static_files/assets/index-0e31b727.css +0 -0
  211. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/static_files/favicon.ico +0 -0
  212. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/static_files/index.html +0 -0
  213. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/static_files/memgpt_logo_transparent.png +0 -0
  214. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/utils.py +0 -0
  215. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/ws_api/__init__.py +0 -0
  216. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/ws_api/example_client.py +0 -0
  217. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/ws_api/interface.py +0 -0
  218. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/ws_api/protocol.py +0 -0
  219. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/server/ws_api/server.py +0 -0
  220. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/services/__init__.py +0 -0
  221. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/services/agent_manager.py +0 -0
  222. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/services/block_manager.py +0 -0
  223. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/services/helpers/agent_manager_helper.py +0 -0
  224. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/services/job_manager.py +0 -0
  225. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/services/message_manager.py +0 -0
  226. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/services/organization_manager.py +0 -0
  227. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/services/passage_manager.py +0 -0
  228. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/services/per_agent_lock_manager.py +0 -0
  229. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/services/source_manager.py +0 -0
  230. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/services/user_manager.py +0 -0
  231. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/streaming_interface.py +0 -0
  232. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/streaming_utils.py +0 -0
  233. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/system.py +0 -0
  234. {letta_nightly-0.6.8.dev20250110190527 → letta_nightly-0.6.8.dev20250111030335}/letta/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: letta-nightly
3
- Version: 0.6.8.dev20250110190527
3
+ Version: 0.6.8.dev20250111030335
4
4
  Summary: Create LLM agents with long-term memory and custom tools
5
5
  License: Apache License
6
6
  Author: Letta Team
@@ -7,11 +7,11 @@ from abc import ABC, abstractmethod
7
7
  from typing import List, Optional, Tuple, Union
8
8
 
9
9
  from letta.constants import (
10
- BASE_TOOLS,
11
10
  CLI_WARNING_PREFIX,
12
11
  ERROR_MESSAGE_PREFIX,
13
12
  FIRST_MESSAGE_ATTEMPTS,
14
13
  FUNC_FAILED_HEARTBEAT_MESSAGE,
14
+ LETTA_CORE_TOOL_MODULE_NAME,
15
15
  LLM_MAX_TOKENS,
16
16
  MESSAGE_SUMMARY_TRUNC_KEEP_N_LAST,
17
17
  MESSAGE_SUMMARY_TRUNC_TOKEN_FRAC,
@@ -19,6 +19,7 @@ from letta.constants import (
19
19
  REQ_HEARTBEAT_MESSAGE,
20
20
  )
21
21
  from letta.errors import ContextWindowExceededError
22
+ from letta.functions.functions import get_function_from_module
22
23
  from letta.helpers import ToolRulesSolver
23
24
  from letta.interface import AgentInterface
24
25
  from letta.llm_api.helpers import is_context_overflow_error
@@ -26,6 +27,7 @@ from letta.llm_api.llm_api_tools import create
26
27
  from letta.local_llm.utils import num_tokens_from_functions, num_tokens_from_messages
27
28
  from letta.memory import summarize_messages
28
29
  from letta.orm import User
30
+ from letta.orm.enums import ToolType
29
31
  from letta.schemas.agent import AgentState, AgentStepResponse, UpdateAgent
30
32
  from letta.schemas.block import BlockUpdate
31
33
  from letta.schemas.embedding_config import EmbeddingConfig
@@ -153,7 +155,7 @@ class Agent(BaseAgent):
153
155
  raise ValueError(f"Invalid JSON format in message: {msg.text}")
154
156
  return None
155
157
 
156
- def update_memory_if_change(self, new_memory: Memory) -> bool:
158
+ def update_memory_if_changed(self, new_memory: Memory) -> bool:
157
159
  """
158
160
  Update internal memory object and system prompt if there have been modifications.
159
161
 
@@ -192,39 +194,45 @@ class Agent(BaseAgent):
192
194
  Execute tool modifications and persist the state of the agent.
193
195
  Note: only some agent state modifications will be persisted, such as data in the AgentState ORM and block data
194
196
  """
195
- # TODO: Get rid of this. This whole piece is pretty shady, that we exec the function to just get the type hints for args.
196
- env = {}
197
- env.update(globals())
198
- exec(target_letta_tool.source_code, env)
199
- callable_func = env[target_letta_tool.json_schema["name"]]
200
- spec = inspect.getfullargspec(callable_func).annotations
201
- for name, arg in function_args.items():
202
- if isinstance(function_args[name], dict):
203
- function_args[name] = spec[name](**function_args[name])
204
-
205
197
  # TODO: add agent manager here
206
198
  orig_memory_str = self.agent_state.memory.compile()
207
199
 
208
200
  # TODO: need to have an AgentState object that actually has full access to the block data
209
201
  # this is because the sandbox tools need to be able to access block.value to edit this data
210
202
  try:
211
- # TODO: This is NO BUENO
212
- # TODO: Matching purely by names is extremely problematic, users can create tools with these names and run them in the agent loop
213
- # TODO: We will have probably have to match the function strings exactly for safety
214
- if function_name in BASE_TOOLS:
203
+ if target_letta_tool.tool_type == ToolType.LETTA_CORE:
215
204
  # base tools are allowed to access the `Agent` object and run on the database
205
+ callable_func = get_function_from_module(LETTA_CORE_TOOL_MODULE_NAME, function_name)
216
206
  function_args["self"] = self # need to attach self to arg since it's dynamically linked
217
207
  function_response = callable_func(**function_args)
208
+ elif target_letta_tool.tool_type == ToolType.LETTA_MEMORY_CORE:
209
+ callable_func = get_function_from_module(LETTA_CORE_TOOL_MODULE_NAME, function_name)
210
+ agent_state_copy = self.agent_state.__deepcopy__()
211
+ function_args["agent_state"] = agent_state_copy # need to attach self to arg since it's dynamically linked
212
+ function_response = callable_func(**function_args)
213
+ self.update_memory_if_changed(agent_state_copy.memory)
218
214
  else:
215
+ # TODO: Get rid of this. This whole piece is pretty shady, that we exec the function to just get the type hints for args.
216
+ env = {}
217
+ env.update(globals())
218
+ exec(target_letta_tool.source_code, env)
219
+ callable_func = env[target_letta_tool.json_schema["name"]]
220
+ spec = inspect.getfullargspec(callable_func).annotations
221
+ for name, arg in function_args.items():
222
+ if isinstance(function_args[name], dict):
223
+ function_args[name] = spec[name](**function_args[name])
224
+
219
225
  # execute tool in a sandbox
220
226
  # TODO: allow agent_state to specify which sandbox to execute tools in
221
- sandbox_run_result = ToolExecutionSandbox(function_name, function_args, self.user).run(
222
- agent_state=self.agent_state.__deepcopy__()
223
- )
227
+ # TODO: This is only temporary, can remove after we publish a pip package with this object
228
+ agent_state_copy = self.agent_state.__deepcopy__()
229
+ agent_state_copy.tools = []
230
+
231
+ sandbox_run_result = ToolExecutionSandbox(function_name, function_args, self.user).run(agent_state=agent_state_copy)
224
232
  function_response, updated_agent_state = sandbox_run_result.func_return, sandbox_run_result.agent_state
225
233
  assert orig_memory_str == self.agent_state.memory.compile(), "Memory should not be modified in a sandbox tool"
226
234
  if updated_agent_state is not None:
227
- self.update_memory_if_change(updated_agent_state.memory)
235
+ self.update_memory_if_changed(updated_agent_state.memory)
228
236
  except Exception as e:
229
237
  # Need to catch error here, or else trunction wont happen
230
238
  # TODO: modify to function execution error
@@ -677,7 +685,7 @@ class Agent(BaseAgent):
677
685
  current_persisted_memory = Memory(
678
686
  blocks=[self.block_manager.get_block_by_id(block.id, actor=self.user) for block in self.agent_state.memory.get_blocks()]
679
687
  ) # read blocks from DB
680
- self.update_memory_if_change(current_persisted_memory)
688
+ self.update_memory_if_changed(current_persisted_memory)
681
689
 
682
690
  # Step 1: add user message
683
691
  if isinstance(messages, Message):
@@ -2,12 +2,16 @@ import os
2
2
  from logging import CRITICAL, DEBUG, ERROR, INFO, NOTSET, WARN, WARNING
3
3
 
4
4
  LETTA_DIR = os.path.join(os.path.expanduser("~"), ".letta")
5
+ LETTA_DIR_TOOL_SANDBOX = os.path.join(LETTA_DIR, "tool_sandbox_dir")
5
6
 
6
7
  ADMIN_PREFIX = "/v1/admin"
7
8
  API_PREFIX = "/v1"
8
9
  OPENAI_API_PREFIX = "/openai"
9
10
 
10
11
  COMPOSIO_ENTITY_ENV_VAR_KEY = "COMPOSIO_ENTITY"
12
+ COMPOSIO_TOOL_TAG_NAME = "composio"
13
+
14
+ LETTA_CORE_TOOL_MODULE_NAME = "letta.functions.function_sets.base"
11
15
 
12
16
  # String in the error message for when the context window is too large
13
17
  # Example full message:
@@ -1,3 +1,4 @@
1
+ import importlib
1
2
  import inspect
2
3
  from textwrap import dedent # remove indentation
3
4
  from types import ModuleType
@@ -64,6 +65,70 @@ def parse_source_code(func) -> str:
64
65
  return source_code
65
66
 
66
67
 
68
+ def get_function_from_module(module_name: str, function_name: str):
69
+ """
70
+ Dynamically imports a function from a specified module.
71
+
72
+ Args:
73
+ module_name (str): The name of the module to import (e.g., 'base').
74
+ function_name (str): The name of the function to retrieve.
75
+
76
+ Returns:
77
+ Callable: The imported function.
78
+
79
+ Raises:
80
+ ModuleNotFoundError: If the specified module cannot be found.
81
+ AttributeError: If the function is not found in the module.
82
+ """
83
+ try:
84
+ # Dynamically import the module
85
+ module = importlib.import_module(module_name)
86
+ # Retrieve the function
87
+ return getattr(module, function_name)
88
+ except ModuleNotFoundError:
89
+ raise ModuleNotFoundError(f"Module '{module_name}' not found.")
90
+ except AttributeError:
91
+ raise AttributeError(f"Function '{function_name}' not found in module '{module_name}'.")
92
+
93
+
94
+ def get_json_schema_from_module(module_name: str, function_name: str) -> dict:
95
+ """
96
+ Dynamically loads a specific function from a module and generates its JSON schema.
97
+
98
+ Args:
99
+ module_name (str): The name of the module to import (e.g., 'base').
100
+ function_name (str): The name of the function to retrieve.
101
+
102
+ Returns:
103
+ dict: The JSON schema for the specified function.
104
+
105
+ Raises:
106
+ ModuleNotFoundError: If the specified module cannot be found.
107
+ AttributeError: If the function is not found in the module.
108
+ ValueError: If the attribute is not a user-defined function.
109
+ """
110
+ try:
111
+ # Dynamically import the module
112
+ module = importlib.import_module(module_name)
113
+
114
+ # Retrieve the function
115
+ attr = getattr(module, function_name, None)
116
+
117
+ # Check if it's a user-defined function
118
+ if not (inspect.isfunction(attr) and attr.__module__ == module.__name__):
119
+ raise ValueError(f"'{function_name}' is not a user-defined function in module '{module_name}'")
120
+
121
+ # Generate schema (assuming a `generate_schema` function exists)
122
+ generated_schema = generate_schema(attr)
123
+
124
+ return generated_schema
125
+
126
+ except ModuleNotFoundError:
127
+ raise ModuleNotFoundError(f"Module '{module_name}' not found.")
128
+ except AttributeError:
129
+ raise AttributeError(f"Function '{function_name}' not found in module '{module_name}'.")
130
+
131
+
67
132
  def load_function_set(module: ModuleType) -> dict:
68
133
  """Load the functions and generate schema for them, given a module object"""
69
134
  function_dict = {}
@@ -264,6 +264,7 @@ def convert_google_ai_response_to_chatcompletion(
264
264
  """
265
265
  try:
266
266
  choices = []
267
+ index = 0
267
268
  for candidate in response_json["candidates"]:
268
269
  content = candidate["content"]
269
270
 
@@ -272,86 +273,87 @@ def convert_google_ai_response_to_chatcompletion(
272
273
 
273
274
  parts = content["parts"]
274
275
  # TODO support parts / multimodal
275
- assert len(parts) == 1, f"Multi-part not yet supported:\n{parts}"
276
- response_message = parts[0]
277
-
278
- # Convert the actual message style to OpenAI style
279
- if "functionCall" in response_message and response_message["functionCall"] is not None:
280
- function_call = response_message["functionCall"]
281
- assert isinstance(function_call, dict), function_call
282
- function_name = function_call["name"]
283
- assert isinstance(function_name, str), function_name
284
- function_args = function_call["args"]
285
- assert isinstance(function_args, dict), function_args
286
-
287
- # NOTE: this also involves stripping the inner monologue out of the function
288
- if pull_inner_thoughts_from_args:
289
- from letta.local_llm.constants import INNER_THOUGHTS_KWARG
290
-
291
- assert INNER_THOUGHTS_KWARG in function_args, f"Couldn't find inner thoughts in function args:\n{function_call}"
292
- inner_thoughts = function_args.pop(INNER_THOUGHTS_KWARG)
293
- assert inner_thoughts is not None, f"Expected non-null inner thoughts function arg:\n{function_call}"
294
- else:
295
- inner_thoughts = None
296
-
297
- # Google AI API doesn't generate tool call IDs
298
- openai_response_message = Message(
299
- role="assistant", # NOTE: "model" -> "assistant"
300
- content=inner_thoughts,
301
- tool_calls=[
302
- ToolCall(
303
- id=get_tool_call_id(),
304
- type="function",
305
- function=FunctionCall(
306
- name=function_name,
307
- arguments=clean_json_string_extra_backslash(json_dumps(function_args)),
308
- ),
309
- )
310
- ],
311
- )
312
-
313
- else:
276
+ # TODO support parallel tool calling natively
277
+ # TODO Alternative here is to throw away everything else except for the first part
278
+ for response_message in parts:
279
+ # Convert the actual message style to OpenAI style
280
+ if "functionCall" in response_message and response_message["functionCall"] is not None:
281
+ function_call = response_message["functionCall"]
282
+ assert isinstance(function_call, dict), function_call
283
+ function_name = function_call["name"]
284
+ assert isinstance(function_name, str), function_name
285
+ function_args = function_call["args"]
286
+ assert isinstance(function_args, dict), function_args
287
+
288
+ # NOTE: this also involves stripping the inner monologue out of the function
289
+ if pull_inner_thoughts_from_args:
290
+ from letta.local_llm.constants import INNER_THOUGHTS_KWARG
291
+
292
+ assert INNER_THOUGHTS_KWARG in function_args, f"Couldn't find inner thoughts in function args:\n{function_call}"
293
+ inner_thoughts = function_args.pop(INNER_THOUGHTS_KWARG)
294
+ assert inner_thoughts is not None, f"Expected non-null inner thoughts function arg:\n{function_call}"
295
+ else:
296
+ inner_thoughts = None
297
+
298
+ # Google AI API doesn't generate tool call IDs
299
+ openai_response_message = Message(
300
+ role="assistant", # NOTE: "model" -> "assistant"
301
+ content=inner_thoughts,
302
+ tool_calls=[
303
+ ToolCall(
304
+ id=get_tool_call_id(),
305
+ type="function",
306
+ function=FunctionCall(
307
+ name=function_name,
308
+ arguments=clean_json_string_extra_backslash(json_dumps(function_args)),
309
+ ),
310
+ )
311
+ ],
312
+ )
314
313
 
315
- # Inner thoughts are the content by default
316
- inner_thoughts = response_message["text"]
317
-
318
- # Google AI API doesn't generate tool call IDs
319
- openai_response_message = Message(
320
- role="assistant", # NOTE: "model" -> "assistant"
321
- content=inner_thoughts,
322
- )
314
+ else:
323
315
 
324
- # Google AI API uses different finish reason strings than OpenAI
325
- # OpenAI: 'stop', 'length', 'function_call', 'content_filter', null
326
- # see: https://platform.openai.com/docs/guides/text-generation/chat-completions-api
327
- # Google AI API: FINISH_REASON_UNSPECIFIED, STOP, MAX_TOKENS, SAFETY, RECITATION, OTHER
328
- # see: https://ai.google.dev/api/python/google/ai/generativelanguage/Candidate/FinishReason
329
- finish_reason = candidate["finishReason"]
330
- if finish_reason == "STOP":
331
- openai_finish_reason = (
332
- "function_call"
333
- if openai_response_message.tool_calls is not None and len(openai_response_message.tool_calls) > 0
334
- else "stop"
335
- )
336
- elif finish_reason == "MAX_TOKENS":
337
- openai_finish_reason = "length"
338
- elif finish_reason == "SAFETY":
339
- openai_finish_reason = "content_filter"
340
- elif finish_reason == "RECITATION":
341
- openai_finish_reason = "content_filter"
342
- else:
343
- raise ValueError(f"Unrecognized finish reason in Google AI response: {finish_reason}")
344
-
345
- choices.append(
346
- Choice(
347
- finish_reason=openai_finish_reason,
348
- index=candidate["index"],
349
- message=openai_response_message,
316
+ # Inner thoughts are the content by default
317
+ inner_thoughts = response_message["text"]
318
+
319
+ # Google AI API doesn't generate tool call IDs
320
+ openai_response_message = Message(
321
+ role="assistant", # NOTE: "model" -> "assistant"
322
+ content=inner_thoughts,
323
+ )
324
+
325
+ # Google AI API uses different finish reason strings than OpenAI
326
+ # OpenAI: 'stop', 'length', 'function_call', 'content_filter', null
327
+ # see: https://platform.openai.com/docs/guides/text-generation/chat-completions-api
328
+ # Google AI API: FINISH_REASON_UNSPECIFIED, STOP, MAX_TOKENS, SAFETY, RECITATION, OTHER
329
+ # see: https://ai.google.dev/api/python/google/ai/generativelanguage/Candidate/FinishReason
330
+ finish_reason = candidate["finishReason"]
331
+ if finish_reason == "STOP":
332
+ openai_finish_reason = (
333
+ "function_call"
334
+ if openai_response_message.tool_calls is not None and len(openai_response_message.tool_calls) > 0
335
+ else "stop"
336
+ )
337
+ elif finish_reason == "MAX_TOKENS":
338
+ openai_finish_reason = "length"
339
+ elif finish_reason == "SAFETY":
340
+ openai_finish_reason = "content_filter"
341
+ elif finish_reason == "RECITATION":
342
+ openai_finish_reason = "content_filter"
343
+ else:
344
+ raise ValueError(f"Unrecognized finish reason in Google AI response: {finish_reason}")
345
+
346
+ choices.append(
347
+ Choice(
348
+ finish_reason=openai_finish_reason,
349
+ index=index,
350
+ message=openai_response_message,
351
+ )
350
352
  )
351
- )
353
+ index += 1
352
354
 
353
- if len(choices) > 1:
354
- raise UserWarning(f"Unexpected number of candidates in response (expected 1, got {len(choices)})")
355
+ # if len(choices) > 1:
356
+ # raise UserWarning(f"Unexpected number of candidates in response (expected 1, got {len(choices)})")
355
357
 
356
358
  # NOTE: some of the Google AI APIs show UsageMetadata in the response, but it seems to not exist?
357
359
  # "usageMetadata": {
@@ -1,7 +1,7 @@
1
1
  import uuid
2
2
  from typing import TYPE_CHECKING, List, Optional
3
3
 
4
- from sqlalchemy import JSON, String, UniqueConstraint
4
+ from sqlalchemy import JSON, String
5
5
  from sqlalchemy.orm import Mapped, mapped_column, relationship
6
6
 
7
7
  from letta.orm.block import Block
@@ -27,7 +27,6 @@ if TYPE_CHECKING:
27
27
  class Agent(SqlalchemyBase, OrganizationMixin):
28
28
  __tablename__ = "agents"
29
29
  __pydantic_model__ = PydanticAgentState
30
- __table_args__ = (UniqueConstraint("organization_id", "name", name="unique_org_agent_name"),)
31
30
 
32
31
  # agent generates its own id
33
32
  # TODO: We want to migrate all the ORM models to do this, so we will need to move this to the SqlalchemyBase
@@ -109,6 +108,7 @@ class Agent(SqlalchemyBase, OrganizationMixin):
109
108
  """converts to the basic pydantic model counterpart"""
110
109
  state = {
111
110
  "id": self.id,
111
+ "organization_id": self.organization_id,
112
112
  "name": self.name,
113
113
  "description": self.description,
114
114
  "message_ids": self.message_ids,
@@ -17,6 +17,16 @@ class CommonSqlalchemyMetaMixins(Base):
17
17
  updated_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), server_default=func.now(), server_onupdate=func.now())
18
18
  is_deleted: Mapped[bool] = mapped_column(Boolean, server_default=text("FALSE"))
19
19
 
20
+ def set_updated_at(self, timestamp: Optional[datetime] = None) -> None:
21
+ """
22
+ Set the updated_at timestamp for the model instance.
23
+
24
+ Args:
25
+ timestamp (Optional[datetime]): The timestamp to set.
26
+ If None, uses the current UTC time.
27
+ """
28
+ self.updated_at = timestamp or datetime.utcnow()
29
+
20
30
  def _set_created_and_updated_by_fields(self, actor_id: str) -> None:
21
31
  """Populate created_by_id and last_updated_by_id based on actor."""
22
32
  if not self.created_by_id:
@@ -4,7 +4,7 @@ from sqlalchemy.orm import Mapped, mapped_column, relationship
4
4
 
5
5
  from letta.orm.mixins import OrganizationMixin
6
6
  from letta.orm.sqlalchemy_base import SqlalchemyBase
7
- from letta.providers import Provider as PydanticProvider
7
+ from letta.schemas.providers import Provider as PydanticProvider
8
8
 
9
9
  if TYPE_CHECKING:
10
10
  from letta.orm.organization import Organization
@@ -100,9 +100,13 @@ class SqlalchemyBase(CommonSqlalchemyMetaMixins, Base):
100
100
 
101
101
  if match_all_tags:
102
102
  # Match ALL tags - use subqueries
103
- for tag in tags:
104
- subquery = select(cls.tags.property.mapper.class_.agent_id).where(cls.tags.property.mapper.class_.tag == tag)
105
- query = query.filter(cls.id.in_(subquery))
103
+ subquery = (
104
+ select(cls.tags.property.mapper.class_.agent_id)
105
+ .where(cls.tags.property.mapper.class_.tag.in_(tags))
106
+ .group_by(cls.tags.property.mapper.class_.agent_id)
107
+ .having(func.count() == len(tags))
108
+ )
109
+ query = query.filter(cls.id.in_(subquery))
106
110
  else:
107
111
  # Match ANY tag - use join and filter
108
112
  query = (
@@ -275,6 +279,8 @@ class SqlalchemyBase(CommonSqlalchemyMetaMixins, Base):
275
279
  if actor:
276
280
  self._set_created_and_updated_by_fields(actor.id)
277
281
 
282
+ self.set_updated_at()
283
+
278
284
  with db_session as session:
279
285
  session.add(self)
280
286
  session.commit()
@@ -4,7 +4,7 @@ from sqlalchemy import JSON, String, UniqueConstraint
4
4
  from sqlalchemy.orm import Mapped, mapped_column, relationship
5
5
 
6
6
  # TODO everything in functions should live in this model
7
- from letta.orm.enums import ToolSourceType
7
+ from letta.orm.enums import ToolSourceType, ToolType
8
8
  from letta.orm.mixins import OrganizationMixin
9
9
  from letta.orm.sqlalchemy_base import SqlalchemyBase
10
10
  from letta.schemas.tool import Tool as PydanticTool
@@ -29,12 +29,17 @@ class Tool(SqlalchemyBase, OrganizationMixin):
29
29
  __table_args__ = (UniqueConstraint("name", "organization_id", name="uix_name_organization"),)
30
30
 
31
31
  name: Mapped[str] = mapped_column(doc="The display name of the tool.")
32
+ tool_type: Mapped[ToolType] = mapped_column(
33
+ String,
34
+ default=ToolType.CUSTOM,
35
+ doc="The type of tool. This affects whether or not we generate json_schema and source_code on the fly.",
36
+ )
32
37
  return_char_limit: Mapped[int] = mapped_column(nullable=True, doc="The maximum number of characters the tool can return.")
33
38
  description: Mapped[Optional[str]] = mapped_column(nullable=True, doc="The description of the tool.")
34
39
  tags: Mapped[List] = mapped_column(JSON, doc="Metadata tags used to filter tools.")
35
40
  source_type: Mapped[ToolSourceType] = mapped_column(String, doc="The type of the source code.", default=ToolSourceType.json)
36
41
  source_code: Mapped[Optional[str]] = mapped_column(String, doc="The source code of the function.")
37
- json_schema: Mapped[dict] = mapped_column(JSON, default=lambda: {}, doc="The OAI compatable JSON schema of the function.")
42
+ json_schema: Mapped[Optional[dict]] = mapped_column(JSON, default=lambda: {}, doc="The OAI compatable JSON schema of the function.")
38
43
  module: Mapped[Optional[str]] = mapped_column(
39
44
  String, nullable=True, doc="the module path from which this tool was derived in the codebase."
40
45
  )
@@ -1,3 +1,4 @@
1
+ from datetime import datetime
1
2
  from typing import List, Optional
2
3
 
3
4
  from pydantic import Field, model_validator
@@ -8,7 +9,6 @@ from letta.llm_api.azure_openai_constants import AZURE_MODEL_TO_CONTEXT_LENGTH
8
9
  from letta.schemas.embedding_config import EmbeddingConfig
9
10
  from letta.schemas.letta_base import LettaBase
10
11
  from letta.schemas.llm_config import LLMConfig
11
- from letta.services.organization_manager import OrganizationManager
12
12
 
13
13
 
14
14
  class ProviderBase(LettaBase):
@@ -16,9 +16,15 @@ class ProviderBase(LettaBase):
16
16
 
17
17
 
18
18
  class Provider(ProviderBase):
19
+ id: Optional[str] = Field(None, description="The id of the provider, lazily created by the database manager.")
19
20
  name: str = Field(..., description="The name of the provider")
20
21
  api_key: Optional[str] = Field(None, description="API key used for requests to the provider.")
21
- organization_id: Optional[str] = Field(OrganizationManager.DEFAULT_ORG_ID, description="The organization id of the user")
22
+ organization_id: Optional[str] = Field(None, description="The organization id of the user")
23
+ updated_at: Optional[datetime] = Field(None, description="The last update timestamp of the provider.")
24
+
25
+ def resolve_identifier(self):
26
+ if not self.id:
27
+ self.id = ProviderBase._generate_id(prefix=ProviderBase.__id_prefix__)
22
28
 
23
29
  def list_llm_models(self) -> List[LLMConfig]:
24
30
  return []
@@ -40,7 +46,6 @@ class Provider(ProviderBase):
40
46
  class ProviderCreate(ProviderBase):
41
47
  name: str = Field(..., description="The name of the provider.")
42
48
  api_key: str = Field(..., description="API key used for requests to the provider.")
43
- organization_id: str = Field(..., description="The organization id that this provider information pertains to.")
44
49
 
45
50
 
46
51
  class ProviderUpdate(ProviderBase):
@@ -1,11 +1,12 @@
1
- from typing import Dict, List, Optional
1
+ from typing import Any, Dict, List, Optional
2
2
 
3
3
  from pydantic import Field, model_validator
4
4
 
5
- from letta.constants import FUNCTION_RETURN_CHAR_LIMIT
6
- from letta.functions.functions import derive_openai_json_schema
5
+ from letta.constants import COMPOSIO_TOOL_TAG_NAME, FUNCTION_RETURN_CHAR_LIMIT, LETTA_CORE_TOOL_MODULE_NAME
6
+ from letta.functions.functions import derive_openai_json_schema, get_json_schema_from_module
7
7
  from letta.functions.helpers import generate_composio_tool_wrapper, generate_langchain_tool_wrapper
8
8
  from letta.functions.schema_generator import generate_schema_from_args_schema_v2
9
+ from letta.orm.enums import ToolType
9
10
  from letta.schemas.letta_base import LettaBase
10
11
  from letta.schemas.openai.chat_completions import ToolCall
11
12
 
@@ -28,6 +29,7 @@ class Tool(BaseTool):
28
29
  """
29
30
 
30
31
  id: str = BaseTool.generate_id_field()
32
+ tool_type: ToolType = Field(ToolType.CUSTOM, description="The type of the tool.")
31
33
  description: Optional[str] = Field(None, description="The description of the tool.")
32
34
  source_type: Optional[str] = Field(None, description="The type of the source code.")
33
35
  module: Optional[str] = Field(None, description="The module of the function.")
@@ -36,7 +38,7 @@ class Tool(BaseTool):
36
38
  tags: List[str] = Field([], description="Metadata tags.")
37
39
 
38
40
  # code
39
- source_code: str = Field(..., description="The source code of the function.")
41
+ source_code: Optional[str] = Field(None, description="The source code of the function.")
40
42
  json_schema: Optional[Dict] = Field(None, description="The JSON schema of the function.")
41
43
 
42
44
  # tool configuration
@@ -51,9 +53,19 @@ class Tool(BaseTool):
51
53
  """
52
54
  Populate missing fields: name, description, and json_schema.
53
55
  """
54
- # Derive JSON schema if not provided
55
- if not self.json_schema:
56
- self.json_schema = derive_openai_json_schema(source_code=self.source_code)
56
+ if self.tool_type == ToolType.CUSTOM:
57
+ # If it's a custom tool, we need to ensure source_code is present
58
+ if not self.source_code:
59
+ raise ValueError(f"Custom tool with id={self.id} is missing source_code field.")
60
+
61
+ # Always derive json_schema for freshest possible json_schema
62
+ # TODO: Instead of checking the tag, we should having `COMPOSIO` as a specific ToolType
63
+ # TODO: We skip this for Composio bc composio json schemas are derived differently
64
+ if not (COMPOSIO_TOOL_TAG_NAME in self.tags):
65
+ self.json_schema = derive_openai_json_schema(source_code=self.source_code)
66
+ elif self.tool_type in {ToolType.LETTA_CORE, ToolType.LETTA_MEMORY_CORE}:
67
+ # If it's letta core tool, we generate the json_schema on the fly here
68
+ self.json_schema = get_json_schema_from_module(module_name=LETTA_CORE_TOOL_MODULE_NAME, function_name=self.name)
57
69
 
58
70
  # Derive name from the JSON schema if not provided
59
71
  if not self.name:
@@ -125,7 +137,7 @@ class ToolCreate(LettaBase):
125
137
 
126
138
  description = composio_tool.description
127
139
  source_type = "python"
128
- tags = ["composio"]
140
+ tags = [COMPOSIO_TOOL_TAG_NAME]
129
141
  wrapper_func_name, wrapper_function_str = generate_composio_tool_wrapper(action_name)
130
142
  json_schema = generate_schema_from_args_schema_v2(composio_tool.args_schema, name=wrapper_func_name, description=description)
131
143
 
@@ -215,7 +227,7 @@ class ToolUpdate(LettaBase):
215
227
 
216
228
  class ToolRunFromSource(LettaBase):
217
229
  source_code: str = Field(..., description="The source code of the function.")
218
- args: Dict[str, str] = Field(..., description="The arguments to pass to the tool.")
230
+ args: Dict[str, Any] = Field(..., description="The arguments to pass to the tool.")
219
231
  env_vars: Dict[str, str] = Field(None, description="The environment variables to pass to the tool.")
220
232
  name: Optional[str] = Field(None, description="The name of the tool to run.")
221
233
  source_type: Optional[str] = Field(None, description="The type of the source code.")
@@ -244,10 +244,6 @@ def create_application() -> "FastAPI":
244
244
  # / static files
245
245
  mount_static_files(app)
246
246
 
247
- @app.on_event("startup")
248
- def on_startup():
249
- generate_openapi_schema(app)
250
-
251
247
  @app.on_event("shutdown")
252
248
  def on_shutdown():
253
249
  global server
@@ -198,10 +198,6 @@ class QueuingInterface(AgentInterface):
198
198
  assert is_utc_datetime(msg_obj.created_at), msg_obj.created_at
199
199
  new_message["date"] = msg_obj.created_at.isoformat()
200
200
  else:
201
- # FIXME this is a total hack
202
- assert self.buffer.qsize() > 1, "Tried to reach back to grab function call data, but couldn't find a buffer message."
203
- # TODO also should not be accessing protected member here
204
-
205
201
  new_message["id"] = self.buffer.queue[-1]["message_api"]["id"]
206
202
  # assert is_utc_datetime(msg_obj.created_at), msg_obj.created_at
207
203
  new_message["date"] = self.buffer.queue[-1]["message_api"]["date"]