mojentic 0.8.4__tar.gz → 1.0.0__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.
- {mojentic-0.8.4/src/mojentic.egg-info → mojentic-1.0.0}/PKG-INFO +76 -27
- {mojentic-0.8.4 → mojentic-1.0.0}/README.md +51 -4
- {mojentic-0.8.4 → mojentic-1.0.0}/pyproject.toml +25 -23
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/async_dispatcher_example.py +12 -4
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/async_llm_example.py +1 -2
- mojentic-1.0.0/src/_examples/broker_as_tool.py +83 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/broker_examples.py +5 -7
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/broker_image_examples.py +1 -1
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/characterize_ollama.py +3 -3
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/characterize_openai.py +1 -1
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/chat_session.py +2 -2
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/chat_session_with_tool.py +2 -2
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/coding_file_tool.py +16 -18
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/current_datetime_tool_example.py +2 -2
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/embeddings.py +1 -1
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/ephemeral_task_manager_example.py +15 -11
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/fetch_openai_models.py +10 -3
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/file_deduplication.py +6 -6
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/file_tool.py +5 -5
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/image_analysis.py +2 -3
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/image_broker.py +1 -1
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/image_broker_splat.py +1 -1
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/iterative_solver.py +3 -3
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/model_characterization.py +2 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/openai_gateway_enhanced_demo.py +15 -5
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/raw.py +1 -1
- mojentic-1.0.0/src/_examples/react/agents/decisioning_agent.py +190 -0
- mojentic-1.0.0/src/_examples/react/agents/summarization_agent.py +89 -0
- mojentic-1.0.0/src/_examples/react/agents/thinking_agent.py +107 -0
- mojentic-1.0.0/src/_examples/react/agents/tool_call_agent.py +83 -0
- mojentic-1.0.0/src/_examples/react/formatters.py +64 -0
- mojentic-1.0.0/src/_examples/react/models/base.py +78 -0
- mojentic-1.0.0/src/_examples/react/models/events.py +96 -0
- mojentic-1.0.0/src/_examples/react.py +82 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/recursive_agent.py +2 -2
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/simple_llm.py +3 -3
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/simple_llm_repl.py +1 -1
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/simple_structured.py +1 -1
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/simple_tool.py +2 -2
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/solver_chat_session.py +5 -11
- mojentic-1.0.0/src/_examples/streaming.py +52 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/tell_user_example.py +4 -4
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/tracer_demo.py +18 -20
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/tracer_qt_viewer.py +49 -46
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/working_memory.py +1 -1
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/__init__.py +3 -3
- mojentic-1.0.0/src/mojentic/agents/__init__.py +34 -0
- mojentic-0.8.4/src/mojentic/agents/agent_broker.py → mojentic-1.0.0/src/mojentic/agents/agent_event_adapter.py +3 -3
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/agents/async_aggregator_agent_spec.py +32 -33
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/agents/async_llm_agent.py +9 -5
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/agents/async_llm_agent_spec.py +21 -22
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/agents/base_async_agent.py +2 -2
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/agents/base_llm_agent.py +6 -2
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/agents/iterative_problem_solver.py +11 -5
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/agents/simple_recursive_agent.py +11 -10
- mojentic-1.0.0/src/mojentic/agents/simple_recursive_agent_spec.py +423 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/async_dispatcher.py +0 -1
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/async_dispatcher_spec.py +1 -1
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/context/__init__.py +0 -2
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/dispatcher.py +7 -8
- mojentic-1.0.0/src/mojentic/llm/__init__.py +16 -0
- mojentic-1.0.0/src/mojentic/llm/gateways/__init__.py +26 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/gateways/anthropic.py +1 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/gateways/anthropic_messages_adapter.py +0 -1
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/gateways/llm_gateway.py +1 -1
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/gateways/ollama.py +23 -18
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/gateways/openai.py +243 -44
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/gateways/openai_message_adapter_spec.py +3 -3
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/gateways/openai_model_registry.py +7 -6
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/gateways/openai_model_registry_spec.py +1 -2
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/gateways/openai_temperature_handling_spec.py +2 -2
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/llm_broker.py +162 -2
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/llm_broker_spec.py +76 -2
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/message_composers.py +6 -3
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/message_composers_spec.py +5 -1
- mojentic-1.0.0/src/mojentic/llm/registry/__init__.py +3 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/registry/populate_registry_from_ollama.py +2 -2
- mojentic-1.0.0/src/mojentic/llm/tools/__init__.py +9 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/tools/ask_user_tool.py +11 -5
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/tools/current_datetime.py +9 -6
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/tools/date_resolver.py +10 -4
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/tools/date_resolver_spec.py +0 -1
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/tools/ephemeral_task_manager/append_task_tool.py +4 -1
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/tools/ephemeral_task_manager/ephemeral_task_list.py +1 -1
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/tools/ephemeral_task_manager/insert_task_after_tool.py +4 -1
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/tools/ephemeral_task_manager/prepend_task_tool.py +5 -2
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/tools/file_manager.py +131 -28
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/tools/file_manager_spec.py +0 -3
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/tools/llm_tool.py +1 -1
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/tools/llm_tool_spec.py +0 -2
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/tools/organic_web_search.py +4 -2
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/tools/tell_user_tool.py +6 -2
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/tools/tool_wrapper.py +2 -2
- mojentic-1.0.0/src/mojentic/tracer/__init__.py +12 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/tracer/event_store.py +7 -8
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/tracer/event_store_spec.py +1 -2
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/tracer/null_tracer.py +37 -43
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/tracer/tracer_events.py +8 -2
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/tracer/tracer_events_spec.py +6 -7
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/tracer/tracer_system.py +37 -36
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/tracer/tracer_system_spec.py +21 -6
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/utils/__init__.py +1 -1
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/utils/formatting.py +1 -0
- {mojentic-0.8.4 → mojentic-1.0.0/src/mojentic.egg-info}/PKG-INFO +76 -27
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic.egg-info/SOURCES.txt +4 -1
- mojentic-1.0.0/src/mojentic.egg-info/requires.txt +27 -0
- mojentic-0.8.4/src/_examples/broker_as_tool.py +0 -58
- mojentic-0.8.4/src/_examples/react/agents/decisioning_agent.py +0 -32
- mojentic-0.8.4/src/_examples/react/agents/thinking_agent.py +0 -37
- mojentic-0.8.4/src/_examples/react/formatters.py +0 -30
- mojentic-0.8.4/src/_examples/react/models/base.py +0 -29
- mojentic-0.8.4/src/_examples/react/models/events.py +0 -28
- mojentic-0.8.4/src/_examples/react.py +0 -32
- mojentic-0.8.4/src/_examples/streaming.py +0 -34
- mojentic-0.8.4/src/mojentic/agents/__init__.py +0 -16
- mojentic-0.8.4/src/mojentic/llm/__init__.py +0 -16
- mojentic-0.8.4/src/mojentic/llm/gateways/__init__.py +0 -25
- mojentic-0.8.4/src/mojentic/llm/registry/__init__.py +0 -6
- mojentic-0.8.4/src/mojentic/llm/tools/__init__.py +0 -18
- mojentic-0.8.4/src/mojentic/tracer/__init__.py +0 -21
- mojentic-0.8.4/src/mojentic.egg-info/requires.txt +0 -25
- {mojentic-0.8.4 → mojentic-1.0.0}/LICENSE.md +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/setup.cfg +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/__init__.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/design_analysis.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/ensures_files_exist.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/list_models.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/oversized_embeddings.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/react/__init__.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/react/agents/__init__.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/react/models/__init__.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/_examples/routed_send_response.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/agents/async_aggregator_agent.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/agents/base_agent.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/agents/base_llm_agent_spec.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/agents/correlation_aggregator_agent.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/agents/output_agent.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/context/shared_working_memory.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/event.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/chat_session.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/chat_session_spec.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/gateways/embeddings_gateway.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/gateways/file_gateway.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/gateways/models.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/gateways/ollama_messages_adapter.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/gateways/ollama_messages_adapter_spec.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/gateways/openai_messages_adapter.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/gateways/openai_spec.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/gateways/tokenizer_gateway.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/registry/llm_registry.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/registry/models.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/tools/ephemeral_task_manager/__init__.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/tools/ephemeral_task_manager/append_task_tool_spec.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/tools/ephemeral_task_manager/clear_tasks_tool.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/tools/ephemeral_task_manager/clear_tasks_tool_spec.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/tools/ephemeral_task_manager/complete_task_tool.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/tools/ephemeral_task_manager/complete_task_tool_spec.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/tools/ephemeral_task_manager/ephemeral_task_list_spec.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/tools/ephemeral_task_manager/insert_task_after_tool_spec.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/tools/ephemeral_task_manager/list_tasks_tool.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/tools/ephemeral_task_manager/list_tasks_tool_spec.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/tools/ephemeral_task_manager/prepend_task_tool_spec.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/tools/ephemeral_task_manager/start_task_tool.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/tools/ephemeral_task_manager/start_task_tool_spec.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/llm/tools/tool_wrapper_spec.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/router.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic/router_spec.py +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/src/mojentic.egg-info/dependency_links.txt +0 -0
- {mojentic-0.8.4 → mojentic-1.0.0}/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.
|
|
3
|
+
Version: 1.0.0
|
|
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,30 +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.8.0
|
|
15
|
+
Requires-Dist: structlog>=25.5.0
|
|
16
|
+
Requires-Dist: numpy>=2.3.5
|
|
17
|
+
Requires-Dist: ollama>=0.1.6
|
|
18
|
+
Requires-Dist: openai>=2.8.1
|
|
19
|
+
Requires-Dist: anthropic>=0.74.1
|
|
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>=
|
|
27
|
-
Requires-Dist: pytest-asyncio; extra == "dev"
|
|
28
|
-
Requires-Dist: pytest-spec; extra == "dev"
|
|
29
|
-
Requires-Dist: pytest-cov; extra == "dev"
|
|
26
|
+
Requires-Dist: pytest>=9.0.1; 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
30
|
Requires-Dist: pytest-mock>=3.10.0; extra == "dev"
|
|
31
|
-
Requires-Dist: flake8>=
|
|
32
|
-
Requires-Dist:
|
|
33
|
-
Requires-Dist:
|
|
34
|
-
Requires-Dist: mkdocs
|
|
35
|
-
Requires-Dist:
|
|
36
|
-
Requires-Dist:
|
|
37
|
-
Requires-Dist:
|
|
31
|
+
Requires-Dist: flake8>=7.3.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>=1.5.2; extra == "dev"
|
|
35
|
+
Requires-Dist: mkdocs-material>=9.6.10; 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"
|
|
38
40
|
Dynamic: license-file
|
|
39
41
|
|
|
40
42
|
# Mojentic
|
|
@@ -64,16 +66,26 @@ Mojentic is a framework that provides a simple and flexible way to interact with
|
|
|
64
66
|
|
|
65
67
|
## 🔧 Installation
|
|
66
68
|
|
|
69
|
+
We recommend using [uv](https://docs.astral.sh/uv/) for fast, reliable Python project management.
|
|
70
|
+
|
|
67
71
|
```bash
|
|
68
|
-
# Install from PyPI
|
|
72
|
+
# Install from PyPI using uv
|
|
73
|
+
uv pip install mojentic
|
|
74
|
+
|
|
75
|
+
# Or with pip
|
|
69
76
|
pip install mojentic
|
|
70
77
|
```
|
|
71
78
|
|
|
72
|
-
Or install from source
|
|
79
|
+
Or install from source:
|
|
73
80
|
|
|
74
81
|
```bash
|
|
75
82
|
git clone https://github.com/svetzal/mojentic.git
|
|
76
83
|
cd mojentic
|
|
84
|
+
|
|
85
|
+
# Using uv (recommended)
|
|
86
|
+
uv sync
|
|
87
|
+
|
|
88
|
+
# Or with pip
|
|
77
89
|
pip install -e .
|
|
78
90
|
```
|
|
79
91
|
|
|
@@ -91,7 +103,7 @@ openai_llm = LLMBroker(model="gpt-5", gateway=OpenAIGateway(api_key="your_api_ke
|
|
|
91
103
|
# Or use other models: "gpt-4o", "gpt-4.1", "o1-mini", "o3-mini", etc.
|
|
92
104
|
|
|
93
105
|
# Or use Ollama for local LLMs
|
|
94
|
-
ollama_llm = LLMBroker(model="
|
|
106
|
+
ollama_llm = LLMBroker(model="qwen3:32b")
|
|
95
107
|
|
|
96
108
|
# Simple text generation
|
|
97
109
|
result = openai_llm.generate(messages=[LLMMessage(content='Hello, how are you?')])
|
|
@@ -121,6 +133,35 @@ result = openai_llm.generate(messages=[
|
|
|
121
133
|
print(result)
|
|
122
134
|
```
|
|
123
135
|
|
|
136
|
+
## 🔑 OpenAI configuration
|
|
137
|
+
|
|
138
|
+
OpenAIGateway now supports environment-variable defaults so you can get started without hardcoding secrets:
|
|
139
|
+
|
|
140
|
+
- If you omit `api_key`, it will use the `OPENAI_API_KEY` environment variable.
|
|
141
|
+
- If you omit `base_url`, it will use the `OPENAI_API_ENDPOINT` environment variable (useful for custom endpoints like Azure/OpenAI-compatible proxies).
|
|
142
|
+
- Precedence: values you pass explicitly to `OpenAIGateway(api_key=..., base_url=...)` always override environment variables.
|
|
143
|
+
|
|
144
|
+
Examples:
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
from mojentic.llm import LLMBroker
|
|
148
|
+
from mojentic.llm.gateways import OpenAIGateway
|
|
149
|
+
|
|
150
|
+
# 1) Easiest: rely on environment variables
|
|
151
|
+
# export OPENAI_API_KEY=sk-...
|
|
152
|
+
# export OPENAI_API_ENDPOINT=https://api.openai.com/v1 # optional
|
|
153
|
+
llm = LLMBroker(
|
|
154
|
+
model="gpt-4o-mini",
|
|
155
|
+
gateway=OpenAIGateway() # picks up OPENAI_API_KEY/OPENAI_API_ENDPOINT automatically
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
# 2) Explicitly override one or both values
|
|
159
|
+
llm = LLMBroker(
|
|
160
|
+
model="gpt-4o-mini",
|
|
161
|
+
gateway=OpenAIGateway(api_key="your_key", base_url="https://api.openai.com/v1")
|
|
162
|
+
)
|
|
163
|
+
```
|
|
164
|
+
|
|
124
165
|
## 🤖 OpenAI Model Support
|
|
125
166
|
|
|
126
167
|
The framework automatically handles parameter differences between model types, so you can switch between any models without code changes.
|
|
@@ -163,11 +204,19 @@ Visit [the documentation](https://svetzal.github.io/mojentic/) for comprehensive
|
|
|
163
204
|
git clone https://github.com/svetzal/mojentic.git
|
|
164
205
|
cd mojentic
|
|
165
206
|
|
|
166
|
-
#
|
|
207
|
+
# Using uv (recommended)
|
|
208
|
+
uv sync --extra dev
|
|
209
|
+
|
|
210
|
+
# Or with pip
|
|
167
211
|
pip install -e ".[dev]"
|
|
168
212
|
|
|
169
213
|
# Run tests
|
|
170
214
|
pytest
|
|
215
|
+
|
|
216
|
+
# Quality checks
|
|
217
|
+
flake8 src # Linting
|
|
218
|
+
bandit -r src # Security scan
|
|
219
|
+
pip-audit # Dependency vulnerabilities
|
|
171
220
|
```
|
|
172
221
|
|
|
173
222
|
## ✅ Project Status
|
|
@@ -25,16 +25,26 @@ Mojentic is a framework that provides a simple and flexible way to interact with
|
|
|
25
25
|
|
|
26
26
|
## 🔧 Installation
|
|
27
27
|
|
|
28
|
+
We recommend using [uv](https://docs.astral.sh/uv/) for fast, reliable Python project management.
|
|
29
|
+
|
|
28
30
|
```bash
|
|
29
|
-
# Install from PyPI
|
|
31
|
+
# Install from PyPI using uv
|
|
32
|
+
uv pip install mojentic
|
|
33
|
+
|
|
34
|
+
# Or with pip
|
|
30
35
|
pip install mojentic
|
|
31
36
|
```
|
|
32
37
|
|
|
33
|
-
Or install from source
|
|
38
|
+
Or install from source:
|
|
34
39
|
|
|
35
40
|
```bash
|
|
36
41
|
git clone https://github.com/svetzal/mojentic.git
|
|
37
42
|
cd mojentic
|
|
43
|
+
|
|
44
|
+
# Using uv (recommended)
|
|
45
|
+
uv sync
|
|
46
|
+
|
|
47
|
+
# Or with pip
|
|
38
48
|
pip install -e .
|
|
39
49
|
```
|
|
40
50
|
|
|
@@ -52,7 +62,7 @@ openai_llm = LLMBroker(model="gpt-5", gateway=OpenAIGateway(api_key="your_api_ke
|
|
|
52
62
|
# Or use other models: "gpt-4o", "gpt-4.1", "o1-mini", "o3-mini", etc.
|
|
53
63
|
|
|
54
64
|
# Or use Ollama for local LLMs
|
|
55
|
-
ollama_llm = LLMBroker(model="
|
|
65
|
+
ollama_llm = LLMBroker(model="qwen3:32b")
|
|
56
66
|
|
|
57
67
|
# Simple text generation
|
|
58
68
|
result = openai_llm.generate(messages=[LLMMessage(content='Hello, how are you?')])
|
|
@@ -82,6 +92,35 @@ result = openai_llm.generate(messages=[
|
|
|
82
92
|
print(result)
|
|
83
93
|
```
|
|
84
94
|
|
|
95
|
+
## 🔑 OpenAI configuration
|
|
96
|
+
|
|
97
|
+
OpenAIGateway now supports environment-variable defaults so you can get started without hardcoding secrets:
|
|
98
|
+
|
|
99
|
+
- If you omit `api_key`, it will use the `OPENAI_API_KEY` environment variable.
|
|
100
|
+
- If you omit `base_url`, it will use the `OPENAI_API_ENDPOINT` environment variable (useful for custom endpoints like Azure/OpenAI-compatible proxies).
|
|
101
|
+
- Precedence: values you pass explicitly to `OpenAIGateway(api_key=..., base_url=...)` always override environment variables.
|
|
102
|
+
|
|
103
|
+
Examples:
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
from mojentic.llm import LLMBroker
|
|
107
|
+
from mojentic.llm.gateways import OpenAIGateway
|
|
108
|
+
|
|
109
|
+
# 1) Easiest: rely on environment variables
|
|
110
|
+
# export OPENAI_API_KEY=sk-...
|
|
111
|
+
# export OPENAI_API_ENDPOINT=https://api.openai.com/v1 # optional
|
|
112
|
+
llm = LLMBroker(
|
|
113
|
+
model="gpt-4o-mini",
|
|
114
|
+
gateway=OpenAIGateway() # picks up OPENAI_API_KEY/OPENAI_API_ENDPOINT automatically
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
# 2) Explicitly override one or both values
|
|
118
|
+
llm = LLMBroker(
|
|
119
|
+
model="gpt-4o-mini",
|
|
120
|
+
gateway=OpenAIGateway(api_key="your_key", base_url="https://api.openai.com/v1")
|
|
121
|
+
)
|
|
122
|
+
```
|
|
123
|
+
|
|
85
124
|
## 🤖 OpenAI Model Support
|
|
86
125
|
|
|
87
126
|
The framework automatically handles parameter differences between model types, so you can switch between any models without code changes.
|
|
@@ -124,11 +163,19 @@ Visit [the documentation](https://svetzal.github.io/mojentic/) for comprehensive
|
|
|
124
163
|
git clone https://github.com/svetzal/mojentic.git
|
|
125
164
|
cd mojentic
|
|
126
165
|
|
|
127
|
-
#
|
|
166
|
+
# Using uv (recommended)
|
|
167
|
+
uv sync --extra dev
|
|
168
|
+
|
|
169
|
+
# Or with pip
|
|
128
170
|
pip install -e ".[dev]"
|
|
129
171
|
|
|
130
172
|
# Run tests
|
|
131
173
|
pytest
|
|
174
|
+
|
|
175
|
+
# Quality checks
|
|
176
|
+
flake8 src # Linting
|
|
177
|
+
bandit -r src # Security scan
|
|
178
|
+
pip-audit # Dependency vulnerabilities
|
|
132
179
|
```
|
|
133
180
|
|
|
134
181
|
## ✅ Project Status
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "mojentic"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "1.0.0"
|
|
4
4
|
authors = [
|
|
5
5
|
{ name = "Stacey Vetzal", email = "stacey@vetzal.com" },
|
|
6
6
|
]
|
|
@@ -14,33 +14,35 @@ classifiers = [
|
|
|
14
14
|
]
|
|
15
15
|
|
|
16
16
|
dependencies = [
|
|
17
|
-
"pydantic",
|
|
18
|
-
"structlog",
|
|
19
|
-
"numpy",
|
|
20
|
-
"ollama",
|
|
21
|
-
"openai",
|
|
22
|
-
"anthropic",
|
|
23
|
-
"tiktoken",
|
|
24
|
-
"parsedatetime",
|
|
25
|
-
"pytz",
|
|
26
|
-
"serpapi",
|
|
27
|
-
"colorama",
|
|
17
|
+
"pydantic>=2.8.0",
|
|
18
|
+
"structlog>=25.5.0",
|
|
19
|
+
"numpy>=2.3.5",
|
|
20
|
+
"ollama>=0.1.6",
|
|
21
|
+
"openai>=2.8.1",
|
|
22
|
+
"anthropic>=0.74.1",
|
|
23
|
+
"tiktoken>=0.12.0",
|
|
24
|
+
"parsedatetime>=2.6",
|
|
25
|
+
"pytz>=2025.2",
|
|
26
|
+
"serpapi>=0.1.5",
|
|
27
|
+
"colorama>=0.4.6",
|
|
28
28
|
]
|
|
29
29
|
|
|
30
30
|
[project.optional-dependencies]
|
|
31
31
|
dev = [
|
|
32
|
-
"pytest>=
|
|
33
|
-
"pytest-asyncio",
|
|
34
|
-
"pytest-spec",
|
|
35
|
-
"pytest-cov",
|
|
32
|
+
"pytest>=9.0.1",
|
|
33
|
+
"pytest-asyncio>=1.3.0",
|
|
34
|
+
"pytest-spec>=5.2.0",
|
|
35
|
+
"pytest-cov>=7.0.0",
|
|
36
36
|
"pytest-mock>=3.10.0",
|
|
37
|
-
"flake8>=
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"mkdocs
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
37
|
+
"flake8>=7.3.0",
|
|
38
|
+
"bandit>=1.7.0",
|
|
39
|
+
"pip-audit>=2.0.0",
|
|
40
|
+
"mkdocs>=1.5.2",
|
|
41
|
+
"mkdocs-material>=9.6.10",
|
|
42
|
+
"mkdocs-llmstxt>=0.4.0",
|
|
43
|
+
"mkdocstrings[python]>=0.21.0",
|
|
44
|
+
"griffe-fieldz>=0.3.0",
|
|
45
|
+
"pymdown-extensions>=10.3",
|
|
44
46
|
]
|
|
45
47
|
|
|
46
48
|
[build-system]
|
|
@@ -62,7 +62,11 @@ class TextAnalyzerAgent(BaseAsyncLLMAgent):
|
|
|
62
62
|
def __init__(self, llm: LLMBroker):
|
|
63
63
|
super().__init__(
|
|
64
64
|
llm=llm,
|
|
65
|
-
behaviour=
|
|
65
|
+
behaviour=(
|
|
66
|
+
"You are a text analysis assistant. "
|
|
67
|
+
"Your job is to provide a detailed analysis of the given text, "
|
|
68
|
+
"including key themes, structure, and notable elements."
|
|
69
|
+
),
|
|
66
70
|
response_model=AnalysisResponse
|
|
67
71
|
)
|
|
68
72
|
|
|
@@ -93,7 +97,11 @@ class TextSummarizerAgent(BaseAsyncLLMAgent):
|
|
|
93
97
|
def __init__(self, llm: LLMBroker):
|
|
94
98
|
super().__init__(
|
|
95
99
|
llm=llm,
|
|
96
|
-
behaviour=
|
|
100
|
+
behaviour=(
|
|
101
|
+
"You are a text summarization assistant. "
|
|
102
|
+
"Your job is to provide concise, accurate summaries of texts "
|
|
103
|
+
"while preserving the key information and main points."
|
|
104
|
+
),
|
|
97
105
|
response_model=SummaryResponse
|
|
98
106
|
)
|
|
99
107
|
|
|
@@ -143,8 +151,8 @@ Analysis: {analysis_event.analysis}
|
|
|
143
151
|
|
|
144
152
|
Summary: {summary_event.summary}
|
|
145
153
|
|
|
146
|
-
Please create a well-structured, insightful report that integrates the analysis and summary,
|
|
147
|
-
highlighting the most important aspects of the text. The report should provide a comprehensive
|
|
154
|
+
Please create a well-structured, insightful report that integrates the analysis and summary,
|
|
155
|
+
highlighting the most important aspects of the text. The report should provide a comprehensive
|
|
148
156
|
understanding of the text's content, structure, and significance.
|
|
149
157
|
"""
|
|
150
158
|
# Create a temporary LLM agent to generate the response
|
|
@@ -5,14 +5,13 @@ This script shows how to create and use asynchronous LLM agents with the AsyncDi
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
import asyncio
|
|
8
|
-
from typing import List
|
|
8
|
+
from typing import List
|
|
9
9
|
|
|
10
10
|
from pydantic import BaseModel, Field
|
|
11
11
|
|
|
12
12
|
from mojentic.agents.async_aggregator_agent import AsyncAggregatorAgent
|
|
13
13
|
from mojentic.agents.async_llm_agent import BaseAsyncLLMAgent
|
|
14
14
|
from mojentic.async_dispatcher import AsyncDispatcher
|
|
15
|
-
from mojentic.context.shared_working_memory import SharedWorkingMemory
|
|
16
15
|
from mojentic.event import Event
|
|
17
16
|
from mojentic.llm import LLMBroker
|
|
18
17
|
from mojentic.router import Router
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from mojentic.agents.base_llm_agent import BaseLLMAgent
|
|
3
|
+
from mojentic.llm.llm_broker import LLMBroker
|
|
4
|
+
from mojentic.llm.tools.date_resolver import ResolveDateTool
|
|
5
|
+
from mojentic.llm.tools.file_manager import ListFilesTool, ReadFileTool, WriteFileTool, FilesystemGateway
|
|
6
|
+
from mojentic.llm.tools.tool_wrapper import ToolWrapper
|
|
7
|
+
|
|
8
|
+
#
|
|
9
|
+
# This is largely a fail, but it was interesting.
|
|
10
|
+
#
|
|
11
|
+
|
|
12
|
+
temporal_specialist = BaseLLMAgent(
|
|
13
|
+
llm=LLMBroker(model="qwen3:7b"),
|
|
14
|
+
tools=[ResolveDateTool()],
|
|
15
|
+
behaviour=(
|
|
16
|
+
"You are a historian and sociologist who focuses on sorting out temporal events, "
|
|
17
|
+
"determining what happened or will happen when."
|
|
18
|
+
)
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
if not os.path.exists("local"):
|
|
22
|
+
os.mkdir("local")
|
|
23
|
+
|
|
24
|
+
# Create a filesystem gateway for the local directory
|
|
25
|
+
fs = FilesystemGateway(base_path="local")
|
|
26
|
+
|
|
27
|
+
knowledge_specialist = BaseLLMAgent(
|
|
28
|
+
llm=LLMBroker(model="qwen3:32b"),
|
|
29
|
+
tools=[
|
|
30
|
+
ListFilesTool(fs),
|
|
31
|
+
ReadFileTool(fs),
|
|
32
|
+
WriteFileTool(fs),
|
|
33
|
+
],
|
|
34
|
+
behaviour=(
|
|
35
|
+
"You are a knowledge management agent who focuses on sorting out facts and information, "
|
|
36
|
+
"able to organize elemental ideas and make connections between them. You can list files "
|
|
37
|
+
"to find out where you stored information, read files to review that information, and "
|
|
38
|
+
"write files to store that information for later retrieval."
|
|
39
|
+
)
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
coordinator = BaseLLMAgent(
|
|
44
|
+
llm=LLMBroker(model="qwen3:32b"),
|
|
45
|
+
behaviour="You are a coordinator who can manage multiple agents and delegate tasks to them to solve problems.",
|
|
46
|
+
tools=[
|
|
47
|
+
ToolWrapper(
|
|
48
|
+
temporal_specialist,
|
|
49
|
+
"temporal_specialist",
|
|
50
|
+
"A historian and sociologist who focuses on sorting out temporal events, figuring out "
|
|
51
|
+
"dates, determining what happened or will happen when."
|
|
52
|
+
),
|
|
53
|
+
ToolWrapper(
|
|
54
|
+
knowledge_specialist,
|
|
55
|
+
"knowledge_specialist",
|
|
56
|
+
"A knowledge management specialist who focuses on sorting out facts and information, "
|
|
57
|
+
"able to organize elemental ideas and make connections between them. Can list files to "
|
|
58
|
+
"find out where you stored information, read files to review that information, and "
|
|
59
|
+
"write files to store that information for later retrieval."
|
|
60
|
+
),
|
|
61
|
+
]
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
result = coordinator.generate_response(
|
|
65
|
+
"""
|
|
66
|
+
I have several things I need to do this week:
|
|
67
|
+
|
|
68
|
+
- On Monday, I need to ensure that I have called Scotiabank and ordered replacement cards for "
|
|
69
|
+
"my current, credit, and line of credit accounts.
|
|
70
|
+
- On Wednesday, I need to drive into Toronto for work. While in Toronto I need to pick up "
|
|
71
|
+
"razors. I need to make sure I see Gregg, Britney and Vikram.
|
|
72
|
+
- On Thursday, I need to ensure I'm up by 7am so that I can be showered and ready for work by 9.
|
|
73
|
+
- On Friday, I need to ensure that I have my laundry done and my bags packed for my trip to "
|
|
74
|
+
"Ottawa.
|
|
75
|
+
|
|
76
|
+
Create me a markdown file for each day of the week, named "YYYY-MM-DD-ToDo.md" where the date "
|
|
77
|
+
"is the date of that day.
|
|
78
|
+
Make a list of to-do items in the markdown file, and add a section for the day's daily notes that "
|
|
79
|
+
"I can fill out each day.
|
|
80
|
+
"""
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
print(result)
|
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import os
|
|
3
|
-
|
|
4
|
-
from mojentic.llm import LLMBroker
|
|
5
|
-
from mojentic.llm.gateways import OpenAIGateway
|
|
6
|
-
|
|
7
|
-
logging.basicConfig(level=logging.WARN)
|
|
8
|
-
|
|
9
3
|
from pathlib import Path
|
|
10
4
|
|
|
11
5
|
from pydantic import BaseModel, Field
|
|
12
6
|
|
|
7
|
+
from mojentic.llm import LLMBroker
|
|
8
|
+
from mojentic.llm.gateways import OpenAIGateway
|
|
13
9
|
from mojentic.llm.gateways.models import LLMMessage
|
|
14
10
|
from mojentic.llm.tools.date_resolver import ResolveDateTool
|
|
15
11
|
|
|
12
|
+
logging.basicConfig(level=logging.WARN)
|
|
13
|
+
|
|
16
14
|
|
|
17
15
|
def openai_llm(model="gpt-5"):
|
|
18
16
|
api_key = os.getenv("OPENAI_API_KEY")
|
|
@@ -21,7 +19,7 @@ def openai_llm(model="gpt-5"):
|
|
|
21
19
|
return llm
|
|
22
20
|
|
|
23
21
|
|
|
24
|
-
def ollama_llm(model="
|
|
22
|
+
def ollama_llm(model="qwen3:32b"):
|
|
25
23
|
llm = LLMBroker(model=model)
|
|
26
24
|
return llm
|
|
27
25
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from ollama import chat
|
|
2
2
|
from pydantic import BaseModel, Field
|
|
3
3
|
|
|
4
|
-
from mojentic.llm.gateways.models import LLMMessage
|
|
4
|
+
from mojentic.llm.gateways.models import LLMMessage
|
|
5
5
|
from mojentic.llm.gateways.ollama import OllamaGateway
|
|
6
6
|
from mojentic.llm.tools.date_resolver import ResolveDateTool
|
|
7
7
|
|
|
@@ -13,7 +13,7 @@ def check_ollama_gateway():
|
|
|
13
13
|
label: str = Field(..., description="The label describing the feeling.")
|
|
14
14
|
|
|
15
15
|
response = gateway.complete(
|
|
16
|
-
model="
|
|
16
|
+
model="qwen3:7b",
|
|
17
17
|
messages=[LLMMessage(content="Hello, how are you?")],
|
|
18
18
|
object_model=Feeling,
|
|
19
19
|
temperature=1.0,
|
|
@@ -25,7 +25,7 @@ def check_ollama_gateway():
|
|
|
25
25
|
|
|
26
26
|
def check_tools_call():
|
|
27
27
|
response = chat(
|
|
28
|
-
model="
|
|
28
|
+
model="qwen3:32b",
|
|
29
29
|
messages=[
|
|
30
30
|
# {
|
|
31
31
|
# 'role': 'user',
|
|
@@ -2,7 +2,7 @@ import os
|
|
|
2
2
|
|
|
3
3
|
from pydantic import BaseModel, Field
|
|
4
4
|
|
|
5
|
-
from mojentic.llm.gateways.models import LLMMessage
|
|
5
|
+
from mojentic.llm.gateways.models import LLMMessage
|
|
6
6
|
from mojentic.llm.gateways.openai import OpenAIGateway
|
|
7
7
|
|
|
8
8
|
api_key = os.getenv("OPENAI_API_KEY")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from mojentic.llm import ChatSession, LLMBroker
|
|
2
2
|
|
|
3
|
-
llm_broker = LLMBroker(model="
|
|
3
|
+
llm_broker = LLMBroker(model="qwen3:32b")
|
|
4
4
|
chat_session = ChatSession(llm_broker)
|
|
5
5
|
|
|
6
6
|
while True:
|
|
@@ -9,4 +9,4 @@ while True:
|
|
|
9
9
|
break
|
|
10
10
|
else:
|
|
11
11
|
response = chat_session.send(query)
|
|
12
|
-
print(response)
|
|
12
|
+
print(response)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from mojentic.llm import ChatSession, LLMBroker
|
|
2
2
|
from mojentic.llm.tools.date_resolver import ResolveDateTool
|
|
3
3
|
|
|
4
|
-
llm_broker = LLMBroker(model="
|
|
4
|
+
llm_broker = LLMBroker(model="qwen3:32b")
|
|
5
5
|
chat_session = ChatSession(llm_broker, tools=[ResolveDateTool()])
|
|
6
6
|
|
|
7
7
|
while True:
|
|
@@ -10,4 +10,4 @@ while True:
|
|
|
10
10
|
break
|
|
11
11
|
else:
|
|
12
12
|
response = chat_session.send(query)
|
|
13
|
-
print(response)
|
|
13
|
+
print(response)
|
|
@@ -30,7 +30,7 @@ from mojentic.llm.tools.file_manager import (
|
|
|
30
30
|
EditFileWithDiffTool, CreateDirectoryTool, FilesystemGateway
|
|
31
31
|
)
|
|
32
32
|
|
|
33
|
-
base_dir = Path(__file__).parent.parent.parent.parent / "code-
|
|
33
|
+
base_dir = Path(__file__).parent.parent.parent.parent / "code-playground3"
|
|
34
34
|
|
|
35
35
|
# Initialize the LLM broker
|
|
36
36
|
|
|
@@ -38,9 +38,7 @@ api_key = os.getenv("OPENAI_API_KEY")
|
|
|
38
38
|
gateway = OpenAIGateway(api_key)
|
|
39
39
|
llm = LLMBroker(model="o4-mini", gateway=gateway)
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
# llm = LLMBroker("llama3.3")
|
|
43
|
-
# llm = LLMBroker(model="qwen3-128k:32b")
|
|
41
|
+
llm = LLMBroker("qwen3-coder:30b")
|
|
44
42
|
|
|
45
43
|
# Create a filesystem gateway for the sandbox
|
|
46
44
|
fs = FilesystemGateway(base_path=str(base_dir))
|
|
@@ -75,28 +73,28 @@ solver = IterativeProblemSolver(
|
|
|
75
73
|
system_prompt="""
|
|
76
74
|
# 0 - Project Identity & Context
|
|
77
75
|
|
|
78
|
-
You are an expert and principled software engineer, well versed in writing Python games. You work
|
|
79
|
-
carefully and purposefully and always check your work with an eye to testability and correctness.
|
|
80
|
-
You know that every line of code you write is a liability, and you take care that every line
|
|
76
|
+
You are an expert and principled software engineer, well versed in writing Python games. You work
|
|
77
|
+
carefully and purposefully and always check your work with an eye to testability and correctness.
|
|
78
|
+
You know that every line of code you write is a liability, and you take care that every line
|
|
81
79
|
matters.
|
|
82
80
|
|
|
83
81
|
# 1 - Universal Engineering Principles
|
|
84
82
|
|
|
85
83
|
* **Code is communication** — optimise for the next human reader.
|
|
86
|
-
* **Simple Design Heuristics** — guiding principles, not iron laws; consult the user when you
|
|
84
|
+
* **Simple Design Heuristics** — guiding principles, not iron laws; consult the user when you
|
|
87
85
|
need to break them.
|
|
88
86
|
1. **All tests pass** — correctness is non‑negotiable.
|
|
89
87
|
2. **Reveals intent** — code should read like an explanation.
|
|
90
|
-
3. **No *****knowledge***** duplication** — avoid multiple spots that must change together;
|
|
88
|
+
3. **No *****knowledge***** duplication** — avoid multiple spots that must change together;
|
|
91
89
|
identical code is only a smell when it hides duplicate *decisions*.
|
|
92
90
|
4. **Minimal entities** — remove unnecessary indirection, classes, or parameters.
|
|
93
91
|
* **Small, safe increments** — single‑reason commits; avoid speculative work (**YAGNI**).
|
|
94
92
|
* **Tests are the executable spec** — red first, green always; test behaviour not implementation.
|
|
95
93
|
* **Compose over inherit**; favour pure functions where practical, avoid side-effects.
|
|
96
|
-
* **Functional core, imperative shell** — isolate pure business logic from I/O and side effects;
|
|
94
|
+
* **Functional core, imperative shell** — isolate pure business logic from I/O and side effects;
|
|
97
95
|
push mutations to the system boundaries, build mockable gateways at those boundaries.
|
|
98
96
|
* **Psychological safety** — review code, not colleagues; critique ideas, not authors.
|
|
99
|
-
* **Version‑control etiquette** — descriptive commit messages, branch from `main`, PRs require
|
|
97
|
+
* **Version‑control etiquette** — descriptive commit messages, branch from `main`, PRs require
|
|
100
98
|
green CI.
|
|
101
99
|
|
|
102
100
|
# 2 - Python‑Specific Conventions
|
|
@@ -115,21 +113,21 @@ green CI.
|
|
|
115
113
|
|
|
116
114
|
## 2.2 Core Libraries
|
|
117
115
|
|
|
118
|
-
Mandatory: pydantic, structlog, pytest, pytest-spec, pytest-cov, pytest-mock, flake8, black,
|
|
119
|
-
pre‑commit, mkdocs‑material. Add new libs only when they eliminate **significant** boilerplate or
|
|
116
|
+
Mandatory: pydantic, structlog, pytest, pytest-spec, pytest-cov, pytest-mock, flake8, black,
|
|
117
|
+
pre‑commit, mkdocs‑material. Add new libs only when they eliminate **significant** boilerplate or
|
|
120
118
|
risk.
|
|
121
119
|
|
|
122
120
|
## 2.3 Project Structure & Imports
|
|
123
121
|
|
|
124
122
|
* **src‑layout**: code in `src/<package_name>/`; tests live beside code as `*_spec.py`.
|
|
125
|
-
* Import order: 1) stdlib, 2) third‑party, 3) first‑party — each group alphabetised with a blank
|
|
123
|
+
* Import order: 1) stdlib, 2) third‑party, 3) first‑party — each group alphabetised with a blank
|
|
126
124
|
line.
|
|
127
125
|
|
|
128
126
|
## 2.4 Naming & Style
|
|
129
127
|
|
|
130
128
|
* `snake_case` for functions & vars, `PascalCase` for classes, `UPPER_SNAKE` for constants.
|
|
131
129
|
* Prefix intentionally unused vars/args with `_`.
|
|
132
|
-
* **flake8** (with plugins) handles linting, and **black** auto‑formats code. Max line length
|
|
130
|
+
* **flake8** (with plugins) handles linting, and **black** auto‑formats code. Max line length
|
|
133
131
|
**100**.
|
|
134
132
|
* Cyclomatic complexity cap: **10** (flake8 `C901`).
|
|
135
133
|
* Use **f‑strings**; avoid magic numbers.
|
|
@@ -144,14 +142,14 @@ line.
|
|
|
144
142
|
|
|
145
143
|
* Configure **structlog** for JSON output by default.
|
|
146
144
|
* Never use `print` for diagnostics; reserve for user‑facing CLI UX.
|
|
147
|
-
* Log levels: `DEBUG` (dev detail) → `INFO` (lifecycle) → `WARNING` (recoverable) → `ERROR` (user
|
|
145
|
+
* Log levels: `DEBUG` (dev detail) → `INFO` (lifecycle) → `WARNING` (recoverable) → `ERROR` (user
|
|
148
146
|
visible).
|
|
149
147
|
|
|
150
148
|
## 2.7 Testing Strategy
|
|
151
149
|
|
|
152
150
|
* **pytest** with **pytest-spec** for specification-style output.
|
|
153
151
|
* Test files end with `_spec.py` and live in the same folder as the code under test.
|
|
154
|
-
* Use **Arrange / Act / Assert** blocks separated by a blank line (no comments) **or** BDD
|
|
152
|
+
* Use **Arrange / Act / Assert** blocks separated by a blank line (no comments) **or** BDD
|
|
155
153
|
`describe/should` classes.
|
|
156
154
|
* Function names: use `should_*` and BDD-style specifications.
|
|
157
155
|
* Class names: use `Describe*` and BDD-style test suites.
|
|
@@ -162,7 +160,7 @@ visible).
|
|
|
162
160
|
# 3 - Planning and Goal Tracking
|
|
163
161
|
|
|
164
162
|
- Use the provided task manager tools to create your plans and work through them step by step.
|
|
165
|
-
- Before declaring yourself finished list all tasks, ensure they are all complete, and that you
|
|
163
|
+
- Before declaring yourself finished list all tasks, ensure they are all complete, and that you
|
|
166
164
|
have not missed any steps
|
|
167
165
|
- If you've missed or forgotten some steps, add them to the task list and continue
|
|
168
166
|
- When all tasks are complete, and you can think of no more to add, declare yourself finished.
|