mojentic 0.8.3__tar.gz → 0.8.4__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.
Files changed (151) hide show
  1. {mojentic-0.8.3 → mojentic-0.8.4}/PKG-INFO +3 -3
  2. {mojentic-0.8.3 → mojentic-0.8.4}/README.md +2 -2
  3. {mojentic-0.8.3 → mojentic-0.8.4}/pyproject.toml +1 -1
  4. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/gateways/openai.py +12 -3
  5. mojentic-0.8.4/src/mojentic/llm/gateways/openai_spec.py +99 -0
  6. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic.egg-info/PKG-INFO +3 -3
  7. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic.egg-info/SOURCES.txt +1 -0
  8. {mojentic-0.8.3 → mojentic-0.8.4}/LICENSE.md +0 -0
  9. {mojentic-0.8.3 → mojentic-0.8.4}/setup.cfg +0 -0
  10. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/__init__.py +0 -0
  11. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/async_dispatcher_example.py +0 -0
  12. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/async_llm_example.py +0 -0
  13. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/broker_as_tool.py +0 -0
  14. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/broker_examples.py +0 -0
  15. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/broker_image_examples.py +0 -0
  16. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/characterize_ollama.py +0 -0
  17. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/characterize_openai.py +0 -0
  18. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/chat_session.py +0 -0
  19. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/chat_session_with_tool.py +0 -0
  20. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/coding_file_tool.py +0 -0
  21. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/current_datetime_tool_example.py +0 -0
  22. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/design_analysis.py +0 -0
  23. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/embeddings.py +0 -0
  24. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/ensures_files_exist.py +0 -0
  25. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/ephemeral_task_manager_example.py +0 -0
  26. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/fetch_openai_models.py +0 -0
  27. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/file_deduplication.py +0 -0
  28. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/file_tool.py +0 -0
  29. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/image_analysis.py +0 -0
  30. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/image_broker.py +0 -0
  31. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/image_broker_splat.py +0 -0
  32. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/iterative_solver.py +0 -0
  33. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/list_models.py +0 -0
  34. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/model_characterization.py +0 -0
  35. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/openai_gateway_enhanced_demo.py +0 -0
  36. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/oversized_embeddings.py +0 -0
  37. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/raw.py +0 -0
  38. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/react/__init__.py +0 -0
  39. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/react/agents/__init__.py +0 -0
  40. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/react/agents/decisioning_agent.py +0 -0
  41. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/react/agents/thinking_agent.py +0 -0
  42. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/react/formatters.py +0 -0
  43. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/react/models/__init__.py +0 -0
  44. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/react/models/base.py +0 -0
  45. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/react/models/events.py +0 -0
  46. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/react.py +0 -0
  47. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/recursive_agent.py +0 -0
  48. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/routed_send_response.py +0 -0
  49. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/simple_llm.py +0 -0
  50. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/simple_llm_repl.py +0 -0
  51. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/simple_structured.py +0 -0
  52. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/simple_tool.py +0 -0
  53. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/solver_chat_session.py +0 -0
  54. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/streaming.py +0 -0
  55. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/tell_user_example.py +0 -0
  56. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/tracer_demo.py +0 -0
  57. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/tracer_qt_viewer.py +0 -0
  58. {mojentic-0.8.3 → mojentic-0.8.4}/src/_examples/working_memory.py +0 -0
  59. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/__init__.py +0 -0
  60. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/agents/__init__.py +0 -0
  61. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/agents/agent_broker.py +0 -0
  62. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/agents/async_aggregator_agent.py +0 -0
  63. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/agents/async_aggregator_agent_spec.py +0 -0
  64. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/agents/async_llm_agent.py +0 -0
  65. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/agents/async_llm_agent_spec.py +0 -0
  66. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/agents/base_agent.py +0 -0
  67. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/agents/base_async_agent.py +0 -0
  68. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/agents/base_llm_agent.py +0 -0
  69. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/agents/base_llm_agent_spec.py +0 -0
  70. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/agents/correlation_aggregator_agent.py +0 -0
  71. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/agents/iterative_problem_solver.py +0 -0
  72. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/agents/output_agent.py +0 -0
  73. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/agents/simple_recursive_agent.py +0 -0
  74. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/async_dispatcher.py +0 -0
  75. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/async_dispatcher_spec.py +0 -0
  76. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/context/__init__.py +0 -0
  77. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/context/shared_working_memory.py +0 -0
  78. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/dispatcher.py +0 -0
  79. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/event.py +0 -0
  80. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/__init__.py +0 -0
  81. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/chat_session.py +0 -0
  82. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/chat_session_spec.py +0 -0
  83. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/gateways/__init__.py +0 -0
  84. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/gateways/anthropic.py +0 -0
  85. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/gateways/anthropic_messages_adapter.py +0 -0
  86. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/gateways/embeddings_gateway.py +0 -0
  87. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/gateways/file_gateway.py +0 -0
  88. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/gateways/llm_gateway.py +0 -0
  89. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/gateways/models.py +0 -0
  90. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/gateways/ollama.py +0 -0
  91. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/gateways/ollama_messages_adapter.py +0 -0
  92. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/gateways/ollama_messages_adapter_spec.py +0 -0
  93. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/gateways/openai_message_adapter_spec.py +0 -0
  94. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/gateways/openai_messages_adapter.py +0 -0
  95. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/gateways/openai_model_registry.py +0 -0
  96. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/gateways/openai_model_registry_spec.py +0 -0
  97. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/gateways/openai_temperature_handling_spec.py +0 -0
  98. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/gateways/tokenizer_gateway.py +0 -0
  99. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/llm_broker.py +0 -0
  100. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/llm_broker_spec.py +0 -0
  101. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/message_composers.py +0 -0
  102. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/message_composers_spec.py +0 -0
  103. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/registry/__init__.py +0 -0
  104. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/registry/llm_registry.py +0 -0
  105. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/registry/models.py +0 -0
  106. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/registry/populate_registry_from_ollama.py +0 -0
  107. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/tools/__init__.py +0 -0
  108. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/tools/ask_user_tool.py +0 -0
  109. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/tools/current_datetime.py +0 -0
  110. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/tools/date_resolver.py +0 -0
  111. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/tools/date_resolver_spec.py +0 -0
  112. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/tools/ephemeral_task_manager/__init__.py +0 -0
  113. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/tools/ephemeral_task_manager/append_task_tool.py +0 -0
  114. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/tools/ephemeral_task_manager/append_task_tool_spec.py +0 -0
  115. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/tools/ephemeral_task_manager/clear_tasks_tool.py +0 -0
  116. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/tools/ephemeral_task_manager/clear_tasks_tool_spec.py +0 -0
  117. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/tools/ephemeral_task_manager/complete_task_tool.py +0 -0
  118. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/tools/ephemeral_task_manager/complete_task_tool_spec.py +0 -0
  119. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/tools/ephemeral_task_manager/ephemeral_task_list.py +0 -0
  120. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/tools/ephemeral_task_manager/ephemeral_task_list_spec.py +0 -0
  121. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/tools/ephemeral_task_manager/insert_task_after_tool.py +0 -0
  122. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/tools/ephemeral_task_manager/insert_task_after_tool_spec.py +0 -0
  123. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/tools/ephemeral_task_manager/list_tasks_tool.py +0 -0
  124. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/tools/ephemeral_task_manager/list_tasks_tool_spec.py +0 -0
  125. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/tools/ephemeral_task_manager/prepend_task_tool.py +0 -0
  126. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/tools/ephemeral_task_manager/prepend_task_tool_spec.py +0 -0
  127. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/tools/ephemeral_task_manager/start_task_tool.py +0 -0
  128. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/tools/ephemeral_task_manager/start_task_tool_spec.py +0 -0
  129. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/tools/file_manager.py +0 -0
  130. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/tools/file_manager_spec.py +0 -0
  131. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/tools/llm_tool.py +0 -0
  132. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/tools/llm_tool_spec.py +0 -0
  133. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/tools/organic_web_search.py +0 -0
  134. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/tools/tell_user_tool.py +0 -0
  135. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/tools/tool_wrapper.py +0 -0
  136. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/llm/tools/tool_wrapper_spec.py +0 -0
  137. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/router.py +0 -0
  138. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/router_spec.py +0 -0
  139. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/tracer/__init__.py +0 -0
  140. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/tracer/event_store.py +0 -0
  141. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/tracer/event_store_spec.py +0 -0
  142. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/tracer/null_tracer.py +0 -0
  143. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/tracer/tracer_events.py +0 -0
  144. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/tracer/tracer_events_spec.py +0 -0
  145. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/tracer/tracer_system.py +0 -0
  146. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/tracer/tracer_system_spec.py +0 -0
  147. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/utils/__init__.py +0 -0
  148. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic/utils/formatting.py +0 -0
  149. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic.egg-info/dependency_links.txt +0 -0
  150. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic.egg-info/requires.txt +0 -0
  151. {mojentic-0.8.3 → mojentic-0.8.4}/src/mojentic.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mojentic
3
- Version: 0.8.3
3
+ Version: 0.8.4
4
4
  Summary: Mojentic is an agentic framework that aims to provide a simple and flexible way to assemble teams of agents to solve complex problems.
5
5
  Author-email: Stacey Vetzal <stacey@vetzal.com>
6
6
  Project-URL: Homepage, https://github.com/svetzal/mojentic
@@ -170,9 +170,9 @@ pip install -e ".[dev]"
170
170
  pytest
171
171
  ```
172
172
 
173
- ## ⚠️ Project Status
173
+ ## Project Status
174
174
 
175
- While the Layer 1 API (LLMBroker, LLMGateway, tool use) has stabilized, the Layer 2 agentic capabilities are under heavy development and will likely change significantly.
175
+ The agentic aspects of this framework are in the highest state of flux. The first layer has stabilized, as have the simpler parts of the second layer, and we're working on the stability of the asynchronous pubsub architecture. We expect Python 3.14 will be the real enabler for the async aspects of the second layer.
176
176
 
177
177
  ## 📄 License
178
178
 
@@ -131,9 +131,9 @@ pip install -e ".[dev]"
131
131
  pytest
132
132
  ```
133
133
 
134
- ## ⚠️ Project Status
134
+ ## Project Status
135
135
 
136
- While the Layer 1 API (LLMBroker, LLMGateway, tool use) has stabilized, the Layer 2 agentic capabilities are under heavy development and will likely change significantly.
136
+ The agentic aspects of this framework are in the highest state of flux. The first layer has stabilized, as have the simpler parts of the second layer, and we're working on the stability of the asynchronous pubsub architecture. We expect Python 3.14 will be the real enabler for the async aspects of the second layer.
137
137
 
138
138
  ## 📄 License
139
139
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "mojentic"
3
- version = "0.8.3"
3
+ version = "0.8.4"
4
4
  authors = [
5
5
  { name = "Stacey Vetzal", email = "stacey@vetzal.com" },
6
6
  ]
@@ -1,4 +1,5 @@
1
1
  import json
2
+ import os
2
3
  from itertools import islice
3
4
  from typing import Type, List, Iterable, Optional
4
5
 
@@ -23,11 +24,19 @@ class OpenAIGateway(LLMGateway):
23
24
 
24
25
  Parameters
25
26
  ----------
26
- api_key : str
27
- The OpenAI API key to use.
27
+ api_key : str, optional
28
+ The OpenAI API key to use. If not provided, defaults to the value of the
29
+ OPENAI_API_KEY environment variable.
30
+ base_url : str, optional
31
+ The base URL for the OpenAI API. If not provided, defaults to the value of the
32
+ OPENAI_API_ENDPOINT environment variable, or None if not set.
28
33
  """
29
34
 
30
- def __init__(self, api_key: str, base_url: Optional[str] = None):
35
+ def __init__(self, api_key: Optional[str] = None, base_url: Optional[str] = None):
36
+ if api_key is None:
37
+ api_key = os.getenv("OPENAI_API_KEY")
38
+ if base_url is None:
39
+ base_url = os.getenv("OPENAI_API_ENDPOINT")
31
40
  self.client = OpenAI(api_key=api_key, base_url=base_url)
32
41
  self.model_registry = get_model_registry()
33
42
 
@@ -0,0 +1,99 @@
1
+ import os
2
+ from unittest.mock import patch
3
+
4
+ from mojentic.llm.gateways.openai import OpenAIGateway
5
+
6
+
7
+ class DescribeOpenAIGateway:
8
+ """
9
+ Unit tests for the OpenAI gateway
10
+ """
11
+
12
+ class DescribeInitialization:
13
+ """
14
+ Tests for OpenAI gateway initialization
15
+ """
16
+
17
+ def should_initialize_with_api_key(self, mocker):
18
+ api_key = "test-api-key"
19
+ mock_openai = mocker.patch('mojentic.llm.gateways.openai.OpenAI')
20
+
21
+ gateway = OpenAIGateway(api_key=api_key)
22
+
23
+ mock_openai.assert_called_once_with(api_key=api_key, base_url=None)
24
+ assert gateway.client is not None
25
+
26
+ def should_initialize_with_api_key_and_base_url(self, mocker):
27
+ api_key = "test-api-key"
28
+ base_url = "https://custom.openai.com"
29
+ mock_openai = mocker.patch('mojentic.llm.gateways.openai.OpenAI')
30
+
31
+ gateway = OpenAIGateway(api_key=api_key, base_url=base_url)
32
+
33
+ mock_openai.assert_called_once_with(api_key=api_key, base_url=base_url)
34
+ assert gateway.client is not None
35
+
36
+ def should_read_api_key_from_environment_variable(self, mocker):
37
+ api_key = "test-api-key-from-env"
38
+ mock_openai = mocker.patch('mojentic.llm.gateways.openai.OpenAI')
39
+
40
+ with patch.dict(os.environ, {'OPENAI_API_KEY': api_key}):
41
+ gateway = OpenAIGateway()
42
+
43
+ mock_openai.assert_called_once_with(api_key=api_key, base_url=None)
44
+ assert gateway.client is not None
45
+
46
+ def should_read_base_url_from_environment_variable(self, mocker):
47
+ api_key = "test-api-key"
48
+ endpoint = "https://corporate.openai.com"
49
+ mock_openai = mocker.patch('mojentic.llm.gateways.openai.OpenAI')
50
+
51
+ with patch.dict(os.environ, {'OPENAI_API_ENDPOINT': endpoint}):
52
+ gateway = OpenAIGateway(api_key=api_key)
53
+
54
+ mock_openai.assert_called_once_with(api_key=api_key, base_url=endpoint)
55
+ assert gateway.client is not None
56
+
57
+ def should_read_both_from_environment_variables(self, mocker):
58
+ api_key = "test-api-key-from-env"
59
+ endpoint = "https://corporate.openai.com"
60
+ mock_openai = mocker.patch('mojentic.llm.gateways.openai.OpenAI')
61
+
62
+ with patch.dict(os.environ, {'OPENAI_API_KEY': api_key, 'OPENAI_API_ENDPOINT': endpoint}):
63
+ gateway = OpenAIGateway()
64
+
65
+ mock_openai.assert_called_once_with(api_key=api_key, base_url=endpoint)
66
+ assert gateway.client is not None
67
+
68
+ def should_prefer_explicit_api_key_over_environment_variable(self, mocker):
69
+ api_key_env = "test-api-key-from-env"
70
+ api_key_explicit = "test-api-key-explicit"
71
+ mock_openai = mocker.patch('mojentic.llm.gateways.openai.OpenAI')
72
+
73
+ with patch.dict(os.environ, {'OPENAI_API_KEY': api_key_env}):
74
+ gateway = OpenAIGateway(api_key=api_key_explicit)
75
+
76
+ mock_openai.assert_called_once_with(api_key=api_key_explicit, base_url=None)
77
+ assert gateway.client is not None
78
+
79
+ def should_prefer_explicit_base_url_over_environment_variable(self, mocker):
80
+ api_key = "test-api-key"
81
+ endpoint_env = "https://corporate.openai.com"
82
+ endpoint_explicit = "https://explicit.openai.com"
83
+ mock_openai = mocker.patch('mojentic.llm.gateways.openai.OpenAI')
84
+
85
+ with patch.dict(os.environ, {'OPENAI_API_ENDPOINT': endpoint_env}):
86
+ gateway = OpenAIGateway(api_key=api_key, base_url=endpoint_explicit)
87
+
88
+ mock_openai.assert_called_once_with(api_key=api_key, base_url=endpoint_explicit)
89
+ assert gateway.client is not None
90
+
91
+ def should_use_none_when_no_endpoint_specified(self, mocker):
92
+ api_key = "test-api-key"
93
+ mock_openai = mocker.patch('mojentic.llm.gateways.openai.OpenAI')
94
+
95
+ with patch.dict(os.environ, {}, clear=True):
96
+ gateway = OpenAIGateway(api_key=api_key)
97
+
98
+ mock_openai.assert_called_once_with(api_key=api_key, base_url=None)
99
+ assert gateway.client is not None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mojentic
3
- Version: 0.8.3
3
+ Version: 0.8.4
4
4
  Summary: Mojentic is an agentic framework that aims to provide a simple and flexible way to assemble teams of agents to solve complex problems.
5
5
  Author-email: Stacey Vetzal <stacey@vetzal.com>
6
6
  Project-URL: Homepage, https://github.com/svetzal/mojentic
@@ -170,9 +170,9 @@ pip install -e ".[dev]"
170
170
  pytest
171
171
  ```
172
172
 
173
- ## ⚠️ Project Status
173
+ ## Project Status
174
174
 
175
- While the Layer 1 API (LLMBroker, LLMGateway, tool use) has stabilized, the Layer 2 agentic capabilities are under heavy development and will likely change significantly.
175
+ The agentic aspects of this framework are in the highest state of flux. The first layer has stabilized, as have the simpler parts of the second layer, and we're working on the stability of the asynchronous pubsub architecture. We expect Python 3.14 will be the real enabler for the async aspects of the second layer.
176
176
 
177
177
  ## 📄 License
178
178
 
@@ -101,6 +101,7 @@ src/mojentic/llm/gateways/openai_message_adapter_spec.py
101
101
  src/mojentic/llm/gateways/openai_messages_adapter.py
102
102
  src/mojentic/llm/gateways/openai_model_registry.py
103
103
  src/mojentic/llm/gateways/openai_model_registry_spec.py
104
+ src/mojentic/llm/gateways/openai_spec.py
104
105
  src/mojentic/llm/gateways/openai_temperature_handling_spec.py
105
106
  src/mojentic/llm/gateways/tokenizer_gateway.py
106
107
  src/mojentic/llm/registry/__init__.py
File without changes
File without changes
File without changes
File without changes