mojentic 0.8.3__py3-none-any.whl → 0.8.4__py3-none-any.whl

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.
@@ -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
 
@@ -87,11 +87,12 @@ mojentic/llm/gateways/models.py,sha256=OyIaMHKrrx6dHo5FbC8qOFct7PRql9wqbe_BJlgDS
87
87
  mojentic/llm/gateways/ollama.py,sha256=OUUImBNzPte52Gsf-e7TBjDHRvYW5flU9ddxwG2zlzk,7909
88
88
  mojentic/llm/gateways/ollama_messages_adapter.py,sha256=kUN_p2FyN88_trXMcL-Xsn9xPBU7pGKlJwTUEUCf6G4,1404
89
89
  mojentic/llm/gateways/ollama_messages_adapter_spec.py,sha256=gVRbWDrHOa1EiZ0CkEWe0pGn-GKRqdGb-x56HBQeYSE,4981
90
- mojentic/llm/gateways/openai.py,sha256=ru156JpPW8-Zs3_O7BCBuztu_PkP88uD0qbM1Y-RMU4,14032
90
+ mojentic/llm/gateways/openai.py,sha256=JNpbcGInAq97Hm4-GS_5IMNTRhUdSIJtIPdAn6fT_jo,14509
91
91
  mojentic/llm/gateways/openai_message_adapter_spec.py,sha256=ITBSV5njldV_x0NPgjmg8Okf9KzevQJ8dTXM-t6ubcg,6612
92
92
  mojentic/llm/gateways/openai_messages_adapter.py,sha256=Scal68JKKdBHB35ok1c5DeWYdD6Wra5oXSsPxJyyXSQ,3947
93
93
  mojentic/llm/gateways/openai_model_registry.py,sha256=CPfbwBhdZ94jzLjmaH9dRXGZFk4OD2pOUlW6RFWVAPM,14101
94
94
  mojentic/llm/gateways/openai_model_registry_spec.py,sha256=rCyXhiCOKMewkZjdZoawALoEk62yjENeYTpjYuMuXDM,6711
95
+ mojentic/llm/gateways/openai_spec.py,sha256=eazIk8bLQ2d9CNPGhcw0WedX7CZz-TEkmwGz74c39CM,4161
95
96
  mojentic/llm/gateways/openai_temperature_handling_spec.py,sha256=PxQpI57RGaWpt1Dj6z2uLeFcP-dRZTHkai-igZTZc9M,9947
96
97
  mojentic/llm/gateways/tokenizer_gateway.py,sha256=ztuqfunlJ6xmyUPPHcC_69-kegiNJD6jdSEde7hDh2w,485
97
98
  mojentic/llm/registry/__init__.py,sha256=P2MHlptrtRPMSWbWl9ojXPmjMwkW0rIn6jwzCkSgnhE,164
@@ -138,8 +139,8 @@ mojentic/tracer/tracer_system.py,sha256=PqAHvG4mxUfkdCOiT0mCrzvPAgPNqiTov5TksEBG
138
139
  mojentic/tracer/tracer_system_spec.py,sha256=TNm0f9LV__coBx0JGEKyzzNN9mFjCSG_SSrRISO8Xeg,8632
139
140
  mojentic/utils/__init__.py,sha256=lqECkkoFvHFttDnafRE1vvh0Dmna_lwupMToP5VvX5k,115
140
141
  mojentic/utils/formatting.py,sha256=bPrwwdluXdQ8TsFxfWtHNOeMWKNvAfABSoUnnA1g7c8,947
141
- mojentic-0.8.3.dist-info/licenses/LICENSE.md,sha256=txSgV8n5zY1W3NiF5HHsCwlaW0e8We1cSC6TuJUqxXA,1060
142
- mojentic-0.8.3.dist-info/METADATA,sha256=wP0ag6Lsy7LCrGosAYf-j1OOjx-xC2B_hhQKOfq1CjQ,6896
143
- mojentic-0.8.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
144
- mojentic-0.8.3.dist-info/top_level.txt,sha256=Q-BvPQ8Eu1jnEqK8Xkr6A9C8Xa1z38oPZRHuA5MCTqg,19
145
- mojentic-0.8.3.dist-info/RECORD,,
142
+ mojentic-0.8.4.dist-info/licenses/LICENSE.md,sha256=txSgV8n5zY1W3NiF5HHsCwlaW0e8We1cSC6TuJUqxXA,1060
143
+ mojentic-0.8.4.dist-info/METADATA,sha256=uwjgOm_Rbx2rFyeh_NDuVNYiSLvBJePbObI0rXelzcU,7039
144
+ mojentic-0.8.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
145
+ mojentic-0.8.4.dist-info/top_level.txt,sha256=Q-BvPQ8Eu1jnEqK8Xkr6A9C8Xa1z38oPZRHuA5MCTqg,19
146
+ mojentic-0.8.4.dist-info/RECORD,,