mojentic 0.9.0__py3-none-any.whl → 1.0.1__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.
Files changed (100) hide show
  1. _examples/async_dispatcher_example.py +12 -4
  2. _examples/async_llm_example.py +1 -2
  3. _examples/broker_as_tool.py +39 -14
  4. _examples/broker_examples.py +4 -6
  5. _examples/characterize_ollama.py +1 -1
  6. _examples/characterize_openai.py +1 -1
  7. _examples/chat_session.py +1 -1
  8. _examples/chat_session_with_tool.py +1 -1
  9. _examples/coding_file_tool.py +1 -3
  10. _examples/current_datetime_tool_example.py +1 -1
  11. _examples/embeddings.py +1 -1
  12. _examples/ephemeral_task_manager_example.py +13 -9
  13. _examples/fetch_openai_models.py +10 -3
  14. _examples/file_deduplication.py +6 -6
  15. _examples/image_analysis.py +2 -3
  16. _examples/image_broker.py +1 -1
  17. _examples/image_broker_splat.py +1 -1
  18. _examples/iterative_solver.py +2 -2
  19. _examples/model_characterization.py +2 -0
  20. _examples/openai_gateway_enhanced_demo.py +15 -5
  21. _examples/raw.py +1 -1
  22. _examples/react/agents/decisioning_agent.py +173 -15
  23. _examples/react/agents/summarization_agent.py +89 -0
  24. _examples/react/agents/thinking_agent.py +84 -14
  25. _examples/react/agents/tool_call_agent.py +83 -0
  26. _examples/react/formatters.py +38 -4
  27. _examples/react/models/base.py +60 -11
  28. _examples/react/models/events.py +76 -8
  29. _examples/react.py +71 -21
  30. _examples/recursive_agent.py +1 -1
  31. _examples/solver_chat_session.py +1 -7
  32. _examples/streaming.py +7 -5
  33. _examples/tell_user_example.py +3 -3
  34. _examples/tracer_demo.py +15 -17
  35. _examples/tracer_qt_viewer.py +49 -46
  36. mojentic/__init__.py +3 -3
  37. mojentic/agents/__init__.py +26 -8
  38. mojentic/agents/{agent_broker.py → agent_event_adapter.py} +3 -3
  39. mojentic/agents/async_aggregator_agent_spec.py +32 -33
  40. mojentic/agents/async_llm_agent.py +9 -5
  41. mojentic/agents/async_llm_agent_spec.py +21 -22
  42. mojentic/agents/base_async_agent.py +2 -2
  43. mojentic/agents/base_llm_agent.py +6 -2
  44. mojentic/agents/iterative_problem_solver.py +11 -5
  45. mojentic/agents/simple_recursive_agent.py +11 -10
  46. mojentic/agents/simple_recursive_agent_spec.py +423 -0
  47. mojentic/async_dispatcher.py +0 -1
  48. mojentic/async_dispatcher_spec.py +1 -1
  49. mojentic/context/__init__.py +0 -2
  50. mojentic/dispatcher.py +7 -8
  51. mojentic/llm/__init__.py +5 -5
  52. mojentic/llm/chat_session.py +24 -1
  53. mojentic/llm/chat_session_spec.py +40 -0
  54. mojentic/llm/gateways/__init__.py +19 -18
  55. mojentic/llm/gateways/anthropic.py +1 -0
  56. mojentic/llm/gateways/anthropic_messages_adapter.py +0 -1
  57. mojentic/llm/gateways/llm_gateway.py +1 -1
  58. mojentic/llm/gateways/ollama.py +2 -0
  59. mojentic/llm/gateways/openai.py +62 -58
  60. mojentic/llm/gateways/openai_message_adapter_spec.py +3 -3
  61. mojentic/llm/gateways/openai_model_registry.py +7 -6
  62. mojentic/llm/gateways/openai_model_registry_spec.py +1 -2
  63. mojentic/llm/gateways/openai_temperature_handling_spec.py +2 -2
  64. mojentic/llm/llm_broker.py +7 -5
  65. mojentic/llm/llm_broker_spec.py +7 -2
  66. mojentic/llm/message_composers.py +6 -3
  67. mojentic/llm/message_composers_spec.py +5 -1
  68. mojentic/llm/registry/__init__.py +0 -3
  69. mojentic/llm/tools/__init__.py +0 -9
  70. mojentic/llm/tools/ask_user_tool.py +11 -5
  71. mojentic/llm/tools/current_datetime.py +9 -6
  72. mojentic/llm/tools/date_resolver.py +10 -4
  73. mojentic/llm/tools/date_resolver_spec.py +0 -1
  74. mojentic/llm/tools/ephemeral_task_manager/append_task_tool.py +4 -1
  75. mojentic/llm/tools/ephemeral_task_manager/ephemeral_task_list.py +1 -1
  76. mojentic/llm/tools/ephemeral_task_manager/insert_task_after_tool.py +4 -1
  77. mojentic/llm/tools/ephemeral_task_manager/prepend_task_tool.py +5 -2
  78. mojentic/llm/tools/file_manager.py +131 -28
  79. mojentic/llm/tools/file_manager_spec.py +0 -3
  80. mojentic/llm/tools/llm_tool.py +1 -1
  81. mojentic/llm/tools/llm_tool_spec.py +0 -2
  82. mojentic/llm/tools/organic_web_search.py +4 -2
  83. mojentic/llm/tools/tell_user_tool.py +6 -2
  84. mojentic/llm/tools/tool_wrapper.py +2 -2
  85. mojentic/tracer/__init__.py +1 -10
  86. mojentic/tracer/event_store.py +7 -8
  87. mojentic/tracer/event_store_spec.py +1 -2
  88. mojentic/tracer/null_tracer.py +37 -43
  89. mojentic/tracer/tracer_events.py +8 -2
  90. mojentic/tracer/tracer_events_spec.py +6 -7
  91. mojentic/tracer/tracer_system.py +37 -36
  92. mojentic/tracer/tracer_system_spec.py +21 -6
  93. mojentic/utils/__init__.py +1 -1
  94. mojentic/utils/formatting.py +1 -0
  95. {mojentic-0.9.0.dist-info → mojentic-1.0.1.dist-info}/METADATA +47 -29
  96. mojentic-1.0.1.dist-info/RECORD +149 -0
  97. {mojentic-0.9.0.dist-info → mojentic-1.0.1.dist-info}/WHEEL +1 -1
  98. mojentic-0.9.0.dist-info/RECORD +0 -146
  99. {mojentic-0.9.0.dist-info → mojentic-1.0.1.dist-info}/licenses/LICENSE.md +0 -0
  100. {mojentic-0.9.0.dist-info → mojentic-1.0.1.dist-info}/top_level.txt +0 -0
@@ -1,10 +1,10 @@
1
1
  """
2
2
  Not sure about this module right now. There are a couple ways to do this.
3
3
  """
4
- from typing import Any, TYPE_CHECKING
4
+ from typing import TYPE_CHECKING
5
5
 
6
6
  from mojentic.llm.tools.llm_tool import LLMTool
7
- from mojentic.llm.gateways.models import LLMMessage, MessageRole
7
+ from mojentic.llm.gateways.models import LLMMessage
8
8
 
9
9
  # Use TYPE_CHECKING to avoid circular imports
10
10
  if TYPE_CHECKING:
@@ -4,18 +4,9 @@ Mojentic tracer module for tracking system operations.
4
4
  """
5
5
 
6
6
  # Core tracer components
7
- from .tracer_system import TracerSystem
8
7
  from .null_tracer import NullTracer
9
- from .event_store import EventStore
10
8
 
11
9
  # Tracer event types
12
- from .tracer_events import (
13
- TracerEvent,
14
- LLMCallTracerEvent,
15
- LLMResponseTracerEvent,
16
- ToolCallTracerEvent,
17
- AgentInteractionTracerEvent
18
- )
19
10
 
20
11
  # Create a singleton NullTracer instance for use throughout the application
21
- null_tracer = NullTracer()
12
+ null_tracer = NullTracer()
@@ -1,6 +1,4 @@
1
- from typing import Any, Callable, Dict, List, Optional, Type, Union
2
- import time
3
- from datetime import datetime
1
+ from typing import Callable, List, Optional, Type
4
2
 
5
3
  from mojentic.event import Event
6
4
  from mojentic.tracer.tracer_events import TracerEvent
@@ -38,11 +36,12 @@ class EventStore:
38
36
  if self.on_store_callback is not None:
39
37
  self.on_store_callback(event)
40
38
 
41
- def get_events(self,
42
- event_type: Optional[Type[Event]] = None,
43
- start_time: Optional[float] = None,
44
- end_time: Optional[float] = None,
45
- filter_func: Optional[Callable[[Event], bool]] = None) -> List[Event]:
39
+ def get_events(
40
+ self,
41
+ event_type: Optional[Type[Event]] = None,
42
+ start_time: Optional[float] = None,
43
+ end_time: Optional[float] = None,
44
+ filter_func: Optional[Callable[[Event], bool]] = None) -> List[Event]:
46
45
  """
47
46
  Get events from the store, optionally filtered by type, time range, and custom filter function.
48
47
 
@@ -1,8 +1,7 @@
1
1
  import time
2
- from typing import List
3
2
 
4
3
  from mojentic import Event
5
- from mojentic.tracer.tracer_events import TracerEvent, LLMCallTracerEvent, AgentInteractionTracerEvent
4
+ from mojentic.tracer.tracer_events import TracerEvent
6
5
  from mojentic.tracer.event_store import EventStore
7
6
 
8
7
 
@@ -32,15 +32,14 @@ class NullTracer:
32
32
  The tracer event to record (will be ignored).
33
33
  """
34
34
  # Do nothing
35
- pass
36
-
37
- def record_llm_call(self,
38
- model: str,
39
- messages: List[Dict],
40
- temperature: float = 1.0,
41
- tools: Optional[List[Dict]] = None,
42
- source: Any = None,
43
- correlation_id: str = None) -> None:
35
+
36
+ def record_llm_call(self,
37
+ model: str,
38
+ messages: List[Dict],
39
+ temperature: float = 1.0,
40
+ tools: Optional[List[Dict]] = None,
41
+ source: Any = None,
42
+ correlation_id: str = None) -> None:
44
43
  """
45
44
  Do nothing implementation of record_llm_call.
46
45
 
@@ -60,15 +59,14 @@ class NullTracer:
60
59
  UUID string that is copied from cause-to-affect for tracing events.
61
60
  """
62
61
  # Do nothing
63
- pass
64
62
 
65
- def record_llm_response(self,
66
- model: str,
67
- content: str,
68
- tool_calls: Optional[List[Dict]] = None,
69
- call_duration_ms: Optional[float] = None,
70
- source: Any = None,
71
- correlation_id: str = None) -> None:
63
+ def record_llm_response(self,
64
+ model: str,
65
+ content: str,
66
+ tool_calls: Optional[List[Dict]] = None,
67
+ call_duration_ms: Optional[float] = None,
68
+ source: Any = None,
69
+ correlation_id: str = None) -> None:
72
70
  """
73
71
  Do nothing implementation of record_llm_response.
74
72
 
@@ -88,16 +86,15 @@ class NullTracer:
88
86
  UUID string that is copied from cause-to-affect for tracing events.
89
87
  """
90
88
  # Do nothing
91
- pass
92
89
 
93
90
  def record_tool_call(self,
94
- tool_name: str,
95
- arguments: Dict[str, Any],
96
- result: Any,
97
- caller: Optional[str] = None,
98
- call_duration_ms: Optional[float] = None,
99
- source: Any = None,
100
- correlation_id: str = None) -> None:
91
+ tool_name: str,
92
+ arguments: Dict[str, Any],
93
+ result: Any,
94
+ caller: Optional[str] = None,
95
+ call_duration_ms: Optional[float] = None,
96
+ source: Any = None,
97
+ correlation_id: str = None) -> None:
101
98
  """
102
99
  Do nothing implementation of record_tool_call.
103
100
 
@@ -119,15 +116,15 @@ class NullTracer:
119
116
  UUID string that is copied from cause-to-affect for tracing events.
120
117
  """
121
118
  # Do nothing
122
- pass
123
-
124
- def record_agent_interaction(self,
125
- from_agent: str,
126
- to_agent: str,
127
- event_type: str,
128
- event_id: Optional[str] = None,
129
- source: Any = None,
130
- correlation_id: str = None) -> None:
119
+
120
+ def record_agent_interaction(
121
+ self,
122
+ from_agent: str,
123
+ to_agent: str,
124
+ event_type: str,
125
+ event_id: Optional[str] = None,
126
+ source: Any = None,
127
+ correlation_id: str = None) -> None:
131
128
  """
132
129
  Do nothing implementation of record_agent_interaction.
133
130
 
@@ -147,13 +144,13 @@ class NullTracer:
147
144
  UUID string that is copied from cause-to-affect for tracing events.
148
145
  """
149
146
  # Do nothing
150
- pass
151
147
 
152
- def get_events(self,
153
- event_type: Optional[Type[TracerEvent]] = None,
154
- start_time: Optional[float] = None,
155
- end_time: Optional[float] = None,
156
- filter_func: Optional[Callable[[TracerEvent], bool]] = None) -> List[TracerEvent]:
148
+ def get_events(
149
+ self,
150
+ event_type: Optional[Type[TracerEvent]] = None,
151
+ start_time: Optional[float] = None,
152
+ end_time: Optional[float] = None,
153
+ filter_func: Optional[Callable[[TracerEvent], bool]] = None) -> List[TracerEvent]:
157
154
  """
158
155
  Return an empty list for any get_events request.
159
156
 
@@ -195,12 +192,9 @@ class NullTracer:
195
192
 
196
193
  def clear(self) -> None:
197
194
  """Do nothing implementation of clear method."""
198
- pass
199
195
 
200
196
  def enable(self) -> None:
201
197
  """No-op method for interface compatibility."""
202
- pass
203
198
 
204
199
  def disable(self) -> None:
205
200
  """No-op method for interface compatibility."""
206
- pass
@@ -1,7 +1,7 @@
1
1
  """
2
2
  Defines tracer event types for tracking system interactions.
3
3
  """
4
- from typing import Any, Dict, List, Optional, Type
4
+ from typing import Any, Dict, List, Optional
5
5
  from datetime import datetime
6
6
  import uuid
7
7
 
@@ -18,7 +18,13 @@ class TracerEvent(Event):
18
18
  They are distinct from regular events which are used for agent communication.
19
19
  """
20
20
  timestamp: float = Field(..., description="Timestamp when the event occurred")
21
- correlation_id: str = Field(default_factory=lambda: str(uuid.uuid4()), description="UUID string that is copied from cause-to-affect for tracing events")
21
+ correlation_id: str = Field(
22
+ default_factory=lambda: str(uuid.uuid4()),
23
+ description=(
24
+ "UUID string that is copied from cause-to-affect "
25
+ "for tracing events"
26
+ )
27
+ )
22
28
 
23
29
  def printable_summary(self) -> str:
24
30
  """
@@ -1,5 +1,4 @@
1
1
  import time
2
- from typing import Dict, List
3
2
 
4
3
  from mojentic.tracer.tracer_events import (
5
4
  TracerEvent,
@@ -24,7 +23,7 @@ class DescribeTracerEvents:
24
23
  source=DescribeTracerEvents,
25
24
  timestamp=time.time()
26
25
  )
27
-
26
+
28
27
  # Then
29
28
  assert isinstance(event, TracerEvent)
30
29
  assert isinstance(event.timestamp, float)
@@ -44,7 +43,7 @@ class DescribeTracerEvents:
44
43
  temperature=0.7,
45
44
  tools=None
46
45
  )
47
-
46
+
48
47
  # Then
49
48
  assert isinstance(event, LLMCallTracerEvent)
50
49
  assert event.model == "test-model"
@@ -64,7 +63,7 @@ class DescribeTracerEvents:
64
63
  content="This is a test response",
65
64
  call_duration_ms=150.5
66
65
  )
67
-
66
+
68
67
  # Then
69
68
  assert isinstance(event, LLMResponseTracerEvent)
70
69
  assert event.model == "test-model"
@@ -86,7 +85,7 @@ class DescribeTracerEvents:
86
85
  result="test result",
87
86
  caller="TestAgent"
88
87
  )
89
-
88
+
90
89
  # Then
91
90
  assert isinstance(event, ToolCallTracerEvent)
92
91
  assert event.tool_name == "test-tool"
@@ -107,10 +106,10 @@ class DescribeTracerEvents:
107
106
  event_type="RequestEvent",
108
107
  event_id="12345"
109
108
  )
110
-
109
+
111
110
  # Then
112
111
  assert isinstance(event, AgentInteractionTracerEvent)
113
112
  assert event.from_agent == "AgentA"
114
113
  assert event.to_agent == "AgentB"
115
114
  assert event.event_type == "RequestEvent"
116
- assert event.event_id == "12345"
115
+ assert event.event_id == "12345"
@@ -4,19 +4,18 @@ TracerSystem module for coordinating tracer events.
4
4
  This provides a central system for recording, filtering, and querying tracer events.
5
5
  """
6
6
  import time
7
- from typing import Any, Callable, Dict, List, Optional, Type, Union
7
+ from typing import Any, Callable, Dict, List, Optional, Type
8
8
 
9
9
  import structlog
10
10
 
11
11
  from mojentic.tracer.tracer_events import (
12
- TracerEvent,
12
+ TracerEvent,
13
13
  LLMCallTracerEvent,
14
14
  LLMResponseTracerEvent,
15
15
  ToolCallTracerEvent,
16
16
  AgentInteractionTracerEvent
17
17
  )
18
18
  from mojentic.tracer.event_store import EventStore
19
- from mojentic.event import Event
20
19
 
21
20
  logger = structlog.get_logger()
22
21
 
@@ -58,13 +57,13 @@ class TracerSystem:
58
57
 
59
58
  self.event_store.store(event)
60
59
 
61
- def record_llm_call(self,
62
- model: str,
63
- messages: List[Dict],
64
- temperature: float = 1.0,
65
- tools: Optional[List[Dict]] = None,
66
- source: Any = None,
67
- correlation_id: str = None) -> None:
60
+ def record_llm_call(self,
61
+ model: str,
62
+ messages: List[Dict],
63
+ temperature: float = 1.0,
64
+ tools: Optional[List[Dict]] = None,
65
+ source: Any = None,
66
+ correlation_id: str = None) -> None:
68
67
  """
69
68
  Record an LLM call event.
70
69
 
@@ -97,13 +96,13 @@ class TracerSystem:
97
96
  )
98
97
  self.event_store.store(event)
99
98
 
100
- def record_llm_response(self,
101
- model: str,
102
- content: str,
103
- tool_calls: Optional[List[Dict]] = None,
104
- call_duration_ms: Optional[float] = None,
105
- source: Any = None,
106
- correlation_id: str = None) -> None:
99
+ def record_llm_response(self,
100
+ model: str,
101
+ content: str,
102
+ tool_calls: Optional[List[Dict]] = None,
103
+ call_duration_ms: Optional[float] = None,
104
+ source: Any = None,
105
+ correlation_id: str = None) -> None:
107
106
  """
108
107
  Record an LLM response event.
109
108
 
@@ -137,13 +136,13 @@ class TracerSystem:
137
136
  self.event_store.store(event)
138
137
 
139
138
  def record_tool_call(self,
140
- tool_name: str,
141
- arguments: Dict[str, Any],
142
- result: Any,
143
- caller: Optional[str] = None,
144
- call_duration_ms: Optional[float] = None,
145
- source: Any = None,
146
- correlation_id: str = None) -> None:
139
+ tool_name: str,
140
+ arguments: Dict[str, Any],
141
+ result: Any,
142
+ caller: Optional[str] = None,
143
+ call_duration_ms: Optional[float] = None,
144
+ source: Any = None,
145
+ correlation_id: str = None) -> None:
147
146
  """
148
147
  Record a tool call event.
149
148
 
@@ -179,13 +178,14 @@ class TracerSystem:
179
178
  )
180
179
  self.event_store.store(event)
181
180
 
182
- def record_agent_interaction(self,
183
- from_agent: str,
184
- to_agent: str,
185
- event_type: str,
186
- event_id: Optional[str] = None,
187
- source: Any = None,
188
- correlation_id: str = None) -> None:
181
+ def record_agent_interaction(
182
+ self,
183
+ from_agent: str,
184
+ to_agent: str,
185
+ event_type: str,
186
+ event_id: Optional[str] = None,
187
+ source: Any = None,
188
+ correlation_id: str = None) -> None:
189
189
  """
190
190
  Record an agent interaction event.
191
191
 
@@ -218,11 +218,12 @@ class TracerSystem:
218
218
  )
219
219
  self.event_store.store(event)
220
220
 
221
- def get_events(self,
222
- event_type: Optional[Type[TracerEvent]] = None,
223
- start_time: Optional[float] = None,
224
- end_time: Optional[float] = None,
225
- filter_func: Optional[Callable[[TracerEvent], bool]] = None) -> List[TracerEvent]:
221
+ def get_events(
222
+ self,
223
+ event_type: Optional[Type[TracerEvent]] = None,
224
+ start_time: Optional[float] = None,
225
+ end_time: Optional[float] = None,
226
+ filter_func: Optional[Callable[[TracerEvent], bool]] = None) -> List[TracerEvent]:
226
227
  """
227
228
  Get tracer events from the store, optionally filtered.
228
229
 
@@ -1,10 +1,7 @@
1
1
  import time
2
- from typing import Dict, List, Optional, Type, Union
3
2
 
4
- import pytest
5
3
 
6
4
  from mojentic.tracer.tracer_events import (
7
- TracerEvent,
8
5
  LLMCallTracerEvent,
9
6
  LLMResponseTracerEvent,
10
7
  ToolCallTracerEvent,
@@ -185,13 +182,31 @@ class DescribeTracerSystem:
185
182
  now = time.time()
186
183
  correlation_id = "test-correlation-id"
187
184
  tracer_system.event_store.store(
188
- LLMCallTracerEvent(source=DescribeTracerSystem, timestamp=now - 100, model="model1", messages=[], correlation_id=correlation_id)
185
+ LLMCallTracerEvent(
186
+ source=DescribeTracerSystem,
187
+ timestamp=now - 100,
188
+ model="model1",
189
+ messages=[],
190
+ correlation_id=correlation_id
191
+ )
189
192
  )
190
193
  tracer_system.event_store.store(
191
- LLMCallTracerEvent(source=DescribeTracerSystem, timestamp=now - 50, model="model2", messages=[], correlation_id=correlation_id)
194
+ LLMCallTracerEvent(
195
+ source=DescribeTracerSystem,
196
+ timestamp=now - 50,
197
+ model="model2",
198
+ messages=[],
199
+ correlation_id=correlation_id
200
+ )
192
201
  )
193
202
  tracer_system.event_store.store(
194
- LLMCallTracerEvent(source=DescribeTracerSystem, timestamp=now, model="model3", messages=[], correlation_id=correlation_id)
203
+ LLMCallTracerEvent(
204
+ source=DescribeTracerSystem,
205
+ timestamp=now,
206
+ model="model3",
207
+ messages=[],
208
+ correlation_id=correlation_id
209
+ )
195
210
  )
196
211
 
197
212
  # When
@@ -2,4 +2,4 @@
2
2
 
3
3
  from .formatting import format_block
4
4
 
5
- __all__ = ['format_block']
5
+ __all__ = ['format_block']
@@ -8,6 +8,7 @@ from colorama import init, Fore, Style
8
8
  # Initialize colorama
9
9
  init()
10
10
 
11
+
11
12
  def format_block(content: str, separator: str = "#" * 39) -> str:
12
13
  """Format a block of text with separator lines for clear console output.
13
14
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mojentic
3
- Version: 0.9.0
3
+ Version: 1.0.1
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
@@ -11,32 +11,32 @@ Classifier: Operating System :: OS Independent
11
11
  Requires-Python: >=3.11
12
12
  Description-Content-Type: text/markdown
13
13
  License-File: LICENSE.md
14
- Requires-Dist: pydantic
15
- Requires-Dist: structlog
16
- Requires-Dist: numpy
17
- Requires-Dist: ollama
18
- Requires-Dist: openai
19
- Requires-Dist: anthropic
20
- Requires-Dist: tiktoken
21
- Requires-Dist: parsedatetime
22
- Requires-Dist: pytz
23
- Requires-Dist: serpapi
24
- Requires-Dist: colorama
14
+ Requires-Dist: pydantic>=2.12.5
15
+ Requires-Dist: structlog>=25.5.0
16
+ Requires-Dist: numpy>=2.3.5
17
+ Requires-Dist: ollama>=0.6.1
18
+ Requires-Dist: openai>=2.12.0
19
+ Requires-Dist: anthropic>=0.75.0
20
+ Requires-Dist: tiktoken>=0.12.0
21
+ Requires-Dist: parsedatetime>=2.6
22
+ Requires-Dist: pytz>=2025.2
23
+ Requires-Dist: serpapi>=0.1.5
24
+ Requires-Dist: colorama>=0.4.6
25
25
  Provides-Extra: dev
26
- Requires-Dist: pytest>=7.0.0; extra == "dev"
27
- Requires-Dist: pytest-asyncio; extra == "dev"
28
- Requires-Dist: pytest-spec; extra == "dev"
29
- Requires-Dist: pytest-cov; extra == "dev"
30
- Requires-Dist: pytest-mock>=3.10.0; extra == "dev"
31
- Requires-Dist: flake8>=6.0.0; extra == "dev"
32
- Requires-Dist: bandit>=1.7.0; extra == "dev"
33
- Requires-Dist: pip-audit>=2.0.0; extra == "dev"
34
- Requires-Dist: mkdocs; extra == "dev"
35
- Requires-Dist: mkdocs-material; extra == "dev"
36
- Requires-Dist: mkdocs-llmstxt; extra == "dev"
37
- Requires-Dist: mkdocstrings[python]; extra == "dev"
38
- Requires-Dist: griffe-fieldz; extra == "dev"
39
- Requires-Dist: pymdown-extensions; extra == "dev"
26
+ Requires-Dist: pytest>=9.0.2; extra == "dev"
27
+ Requires-Dist: pytest-asyncio>=1.3.0; extra == "dev"
28
+ Requires-Dist: pytest-spec>=5.2.0; extra == "dev"
29
+ Requires-Dist: pytest-cov>=7.0.0; extra == "dev"
30
+ Requires-Dist: pytest-mock>=3.15.0; extra == "dev"
31
+ Requires-Dist: flake8>=7.3.0; extra == "dev"
32
+ Requires-Dist: bandit>=1.9.2; extra == "dev"
33
+ Requires-Dist: pip-audit>=2.10.0; extra == "dev"
34
+ Requires-Dist: mkdocs>=1.6.1; extra == "dev"
35
+ Requires-Dist: mkdocs-material>=9.7.0; extra == "dev"
36
+ Requires-Dist: mkdocs-llmstxt>=0.4.0; extra == "dev"
37
+ Requires-Dist: mkdocstrings[python]>=0.21.0; extra == "dev"
38
+ Requires-Dist: griffe-fieldz>=0.3.0; extra == "dev"
39
+ Requires-Dist: pymdown-extensions>=10.3; extra == "dev"
40
40
  Dynamic: license-file
41
41
 
42
42
  # Mojentic
@@ -66,16 +66,26 @@ Mojentic is a framework that provides a simple and flexible way to interact with
66
66
 
67
67
  ## 🔧 Installation
68
68
 
69
+ We recommend using [uv](https://docs.astral.sh/uv/) for fast, reliable Python project management.
70
+
69
71
  ```bash
70
- # Install from PyPI
72
+ # Install from PyPI using uv
73
+ uv pip install mojentic
74
+
75
+ # Or with pip
71
76
  pip install mojentic
72
77
  ```
73
78
 
74
- Or install from source
79
+ Or install from source:
75
80
 
76
81
  ```bash
77
82
  git clone https://github.com/svetzal/mojentic.git
78
83
  cd mojentic
84
+
85
+ # Using uv (recommended)
86
+ uv sync
87
+
88
+ # Or with pip
79
89
  pip install -e .
80
90
  ```
81
91
 
@@ -194,11 +204,19 @@ Visit [the documentation](https://svetzal.github.io/mojentic/) for comprehensive
194
204
  git clone https://github.com/svetzal/mojentic.git
195
205
  cd mojentic
196
206
 
197
- # Install dependencies
207
+ # Using uv (recommended)
208
+ uv sync --extra dev
209
+
210
+ # Or with pip
198
211
  pip install -e ".[dev]"
199
212
 
200
213
  # Run tests
201
214
  pytest
215
+
216
+ # Quality checks
217
+ flake8 src # Linting
218
+ bandit -r src # Security scan
219
+ pip-audit # Dependency vulnerabilities
202
220
  ```
203
221
 
204
222
  ## ✅ Project Status