mojentic 0.5.4__py3-none-any.whl → 0.5.6__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 (36) hide show
  1. _examples/broker_examples.py +12 -22
  2. _examples/broker_image_examples.py +41 -0
  3. _examples/ephemeral_task_manager_example.py +48 -0
  4. _examples/streaming.py +1 -1
  5. _examples/tell_user_example.py +43 -0
  6. mojentic/llm/gateways/models.py +29 -1
  7. mojentic/llm/llm_broker_spec.py +0 -49
  8. mojentic/llm/message_composers_spec.py +0 -80
  9. mojentic/llm/tools/ask_user_tool.py +1 -1
  10. mojentic/llm/tools/ephemeral_task_manager/__init__.py +27 -0
  11. mojentic/llm/tools/ephemeral_task_manager/append_task_tool.py +77 -0
  12. mojentic/llm/tools/ephemeral_task_manager/append_task_tool_spec.py +34 -0
  13. mojentic/llm/tools/ephemeral_task_manager/clear_tasks_tool.py +57 -0
  14. mojentic/llm/tools/ephemeral_task_manager/clear_tasks_tool_spec.py +32 -0
  15. mojentic/llm/tools/ephemeral_task_manager/complete_task_tool.py +81 -0
  16. mojentic/llm/tools/ephemeral_task_manager/complete_task_tool_spec.py +43 -0
  17. mojentic/llm/tools/ephemeral_task_manager/ephemeral_task_list.py +202 -0
  18. mojentic/llm/tools/ephemeral_task_manager/ephemeral_task_list_spec.py +137 -0
  19. mojentic/llm/tools/ephemeral_task_manager/insert_task_after_tool.py +84 -0
  20. mojentic/llm/tools/ephemeral_task_manager/insert_task_after_tool_spec.py +42 -0
  21. mojentic/llm/tools/ephemeral_task_manager/list_tasks_tool.py +80 -0
  22. mojentic/llm/tools/ephemeral_task_manager/list_tasks_tool_spec.py +38 -0
  23. mojentic/llm/tools/ephemeral_task_manager/prepend_task_tool.py +77 -0
  24. mojentic/llm/tools/ephemeral_task_manager/prepend_task_tool_spec.py +34 -0
  25. mojentic/llm/tools/ephemeral_task_manager/start_task_tool.py +81 -0
  26. mojentic/llm/tools/ephemeral_task_manager/start_task_tool_spec.py +43 -0
  27. mojentic/llm/tools/llm_tool.py +15 -0
  28. mojentic/llm/tools/llm_tool_spec.py +68 -0
  29. mojentic/llm/tools/organic_web_search.py +37 -0
  30. mojentic/llm/tools/tell_user_tool.py +27 -0
  31. {mojentic-0.5.4.dist-info → mojentic-0.5.6.dist-info}/METADATA +1 -1
  32. {mojentic-0.5.4.dist-info → mojentic-0.5.6.dist-info}/RECORD +35 -13
  33. {mojentic-0.5.4.dist-info → mojentic-0.5.6.dist-info}/WHEEL +1 -1
  34. mojentic/llm/tools/web_search.py +0 -35
  35. {mojentic-0.5.4.dist-info → mojentic-0.5.6.dist-info}/licenses/LICENSE.md +0 -0
  36. {mojentic-0.5.4.dist-info → mojentic-0.5.6.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,42 @@
1
+ from unittest.mock import Mock
2
+
3
+ import pytest
4
+
5
+ from mojentic.llm.tools.ephemeral_task_manager.ephemeral_task_list import EphemeralTaskList, Task, TaskStatus
6
+ from mojentic.llm.tools.ephemeral_task_manager.insert_task_after_tool import InsertTaskAfterTool
7
+
8
+
9
+ @pytest.fixture
10
+ def mock_task_list():
11
+ mock = Mock(spec=EphemeralTaskList)
12
+ return mock
13
+
14
+
15
+ @pytest.fixture
16
+ def insert_task_after_tool(mock_task_list):
17
+ return InsertTaskAfterTool(task_list=mock_task_list)
18
+
19
+
20
+ class DescribeInsertTaskAfterTool:
21
+ def should_call_insert_task_after_with_correct_parameters(self, insert_task_after_tool, mock_task_list):
22
+ mock_task = Task(id=2, description="Test task", status=TaskStatus.PENDING)
23
+ mock_task_list.insert_task_after.return_value = mock_task
24
+
25
+ insert_task_after_tool.run(existing_task_id=1, description="Test task")
26
+
27
+ mock_task_list.insert_task_after.assert_called_once_with(existing_task_id=1, description="Test task")
28
+
29
+ def should_convert_string_task_id_to_int(self, insert_task_after_tool, mock_task_list):
30
+ mock_task = Task(id=2, description="Test task", status=TaskStatus.PENDING)
31
+ mock_task_list.insert_task_after.return_value = mock_task
32
+
33
+ insert_task_after_tool.run(existing_task_id="1", description="Test task")
34
+
35
+ mock_task_list.insert_task_after.assert_called_once_with(existing_task_id=1, description="Test task")
36
+
37
+ def should_handle_error_when_insert_task_after_fails(self, insert_task_after_tool, mock_task_list):
38
+ mock_task_list.insert_task_after.side_effect = ValueError("No task with ID '999' exists")
39
+
40
+ insert_task_after_tool.run(existing_task_id=999, description="Test task")
41
+
42
+ mock_task_list.insert_task_after.assert_called_once_with(existing_task_id=999, description="Test task")
@@ -0,0 +1,80 @@
1
+ """
2
+ Tool for listing all tasks in the ephemeral task manager.
3
+ """
4
+
5
+ from typing import Dict, List
6
+
7
+ from mojentic.llm.tools.ephemeral_task_manager.ephemeral_task_list import EphemeralTaskList, Task
8
+ from mojentic.llm.tools.llm_tool import LLMTool
9
+
10
+
11
+ class ListTasksTool(LLMTool):
12
+ """
13
+ Tool for listing all tasks in the ephemeral task manager.
14
+ """
15
+
16
+ def __init__(self, task_list: EphemeralTaskList):
17
+ """
18
+ Initialize the tool with a shared task list.
19
+
20
+ Args:
21
+ task_list: The shared task list to use
22
+ """
23
+ self._task_list = task_list
24
+
25
+ def run(self) -> Dict[str, str]:
26
+ """
27
+ Get all tasks in the list.
28
+
29
+ Returns:
30
+ A dictionary with the result of the operation
31
+ """
32
+ tasks = self._task_list.list_tasks()
33
+
34
+ # Format tasks as a string for the summary
35
+ task_list_str = self._format_tasks(tasks)
36
+
37
+ return {
38
+ "count": str(len(tasks)),
39
+ "tasks": task_list_str,
40
+ "summary": f"Found {len(tasks)} tasks\n\n{task_list_str}"
41
+ }
42
+
43
+ def _format_tasks(self, tasks: List[Task]) -> str:
44
+ """
45
+ Format a list of tasks as a string.
46
+
47
+ Args:
48
+ tasks: The list of tasks to format
49
+
50
+ Returns:
51
+ A formatted string representation of the tasks
52
+ """
53
+ if not tasks:
54
+ return "No tasks found."
55
+
56
+ result = [f"{task.id}. {task.description} ({task.status.value})"
57
+ for i, task in enumerate(tasks)]
58
+
59
+ return "\n".join(result)
60
+
61
+ @property
62
+ def descriptor(self):
63
+ """
64
+ Get the descriptor for the tool.
65
+
66
+ Returns:
67
+ The descriptor dictionary
68
+ """
69
+ return {
70
+ "type": "function",
71
+ "function": {
72
+ "name": "list_tasks",
73
+ "description": "List all tasks in the task list.",
74
+ "parameters": {
75
+ "type": "object",
76
+ "properties": {},
77
+ "additionalProperties": False
78
+ }
79
+ }
80
+ }
@@ -0,0 +1,38 @@
1
+ from unittest.mock import Mock
2
+
3
+ import pytest
4
+
5
+ from mojentic.llm.tools.ephemeral_task_manager.ephemeral_task_list import EphemeralTaskList, Task, TaskStatus
6
+ from mojentic.llm.tools.ephemeral_task_manager.list_tasks_tool import ListTasksTool
7
+
8
+
9
+ @pytest.fixture
10
+ def mock_task_list():
11
+ mock = Mock(spec=EphemeralTaskList)
12
+ return mock
13
+
14
+
15
+ @pytest.fixture
16
+ def list_tasks_tool(mock_task_list):
17
+ return ListTasksTool(task_list=mock_task_list)
18
+
19
+
20
+ class DescribeListTasksTool:
21
+ def should_call_list_tasks(self, list_tasks_tool, mock_task_list):
22
+ mock_tasks = [
23
+ Task(id=1, description="Task 1", status=TaskStatus.PENDING),
24
+ Task(id=2, description="Task 2", status=TaskStatus.IN_PROGRESS),
25
+ Task(id=3, description="Task 3", status=TaskStatus.COMPLETED)
26
+ ]
27
+ mock_task_list.list_tasks.return_value = mock_tasks
28
+
29
+ list_tasks_tool.run()
30
+
31
+ mock_task_list.list_tasks.assert_called_once()
32
+
33
+ def should_handle_empty_list(self, list_tasks_tool, mock_task_list):
34
+ mock_task_list.list_tasks.return_value = []
35
+
36
+ list_tasks_tool.run()
37
+
38
+ mock_task_list.list_tasks.assert_called_once()
@@ -0,0 +1,77 @@
1
+ """
2
+ Tool for prepending a new task to the beginning of the ephemeral task manager list.
3
+ """
4
+
5
+ from typing import Dict
6
+
7
+ from mojentic.llm.tools.llm_tool import LLMTool
8
+ from mojentic.llm.tools.ephemeral_task_manager.ephemeral_task_list import EphemeralTaskList
9
+
10
+
11
+ class PrependTaskTool(LLMTool):
12
+ """
13
+ Tool for prepending a new task to the beginning of the ephemeral task manager list.
14
+ """
15
+
16
+ def __init__(self, task_list: EphemeralTaskList):
17
+ """
18
+ Initialize the tool with a shared task list.
19
+
20
+ Args:
21
+ task_list: The shared task list to use
22
+ """
23
+ self._task_list = task_list
24
+
25
+ def run(self, description: str) -> Dict[str, str]:
26
+ """
27
+ Prepend a new task to the beginning of the list.
28
+
29
+ Args:
30
+ description: The description of the task
31
+
32
+ Returns:
33
+ A dictionary with the result of the operation
34
+
35
+ Raises:
36
+ ValueError: If there's an error adding the task
37
+ """
38
+ try:
39
+ task = self._task_list.prepend_task(description=description)
40
+ return {
41
+ "id": task.id,
42
+ "description": task.description,
43
+ "status": task.status.value,
44
+ "summary": f"Task '{task.id}' prepended successfully"
45
+ }
46
+ except ValueError as e:
47
+ return {
48
+ "error": str(e),
49
+ "summary": f"Failed to prepend task: {str(e)}"
50
+ }
51
+
52
+ @property
53
+ def descriptor(self):
54
+ """
55
+ Get the descriptor for the tool.
56
+
57
+ Returns:
58
+ The descriptor dictionary
59
+ """
60
+ return {
61
+ "type": "function",
62
+ "function": {
63
+ "name": "prepend_task",
64
+ "description": "Prepend a new task to the beginning of the task list with a description. The task will start with 'pending' status.",
65
+ "parameters": {
66
+ "type": "object",
67
+ "properties": {
68
+ "description": {
69
+ "type": "string",
70
+ "description": "The description of the task"
71
+ }
72
+ },
73
+ "required": ["description"],
74
+ "additionalProperties": False
75
+ }
76
+ }
77
+ }
@@ -0,0 +1,34 @@
1
+ from unittest.mock import Mock
2
+
3
+ import pytest
4
+
5
+ from mojentic.llm.tools.ephemeral_task_manager.ephemeral_task_list import EphemeralTaskList, Task, TaskStatus
6
+ from mojentic.llm.tools.ephemeral_task_manager.prepend_task_tool import PrependTaskTool
7
+
8
+
9
+ @pytest.fixture
10
+ def mock_task_list():
11
+ mock = Mock(spec=EphemeralTaskList)
12
+ return mock
13
+
14
+
15
+ @pytest.fixture
16
+ def prepend_task_tool(mock_task_list):
17
+ return PrependTaskTool(task_list=mock_task_list)
18
+
19
+
20
+ class DescribePrependTaskTool:
21
+ def should_call_prepend_task_with_description(self, prepend_task_tool, mock_task_list):
22
+ mock_task = Task(id=1, description="Test task", status=TaskStatus.PENDING)
23
+ mock_task_list.prepend_task.return_value = mock_task
24
+
25
+ prepend_task_tool.run(description="Test task")
26
+
27
+ mock_task_list.prepend_task.assert_called_once_with(description="Test task")
28
+
29
+ def should_handle_error_when_prepend_task_fails(self, prepend_task_tool, mock_task_list):
30
+ mock_task_list.prepend_task.side_effect = ValueError("Test error")
31
+
32
+ prepend_task_tool.run(description="Test task")
33
+
34
+ mock_task_list.prepend_task.assert_called_once_with(description="Test task")
@@ -0,0 +1,81 @@
1
+ """
2
+ Tool for starting a task in the ephemeral task manager.
3
+ """
4
+
5
+ from typing import Dict
6
+
7
+ from mojentic.llm.tools.llm_tool import LLMTool
8
+ from mojentic.llm.tools.ephemeral_task_manager.ephemeral_task_list import EphemeralTaskList
9
+
10
+
11
+ class StartTaskTool(LLMTool):
12
+ """
13
+ Tool for starting a task in the ephemeral task manager.
14
+
15
+ This tool changes a task's status from PENDING to IN_PROGRESS.
16
+ """
17
+
18
+ def __init__(self, task_list: EphemeralTaskList):
19
+ """
20
+ Initialize the tool with a shared task list.
21
+
22
+ Args:
23
+ task_list: The shared task list to use
24
+ """
25
+ self._task_list = task_list
26
+
27
+ def run(self, id: int) -> Dict[str, str]:
28
+ """
29
+ Start a task by changing its status from PENDING to IN_PROGRESS.
30
+
31
+ Args:
32
+ id: The ID of the task to start
33
+
34
+ Returns:
35
+ A dictionary with the result of the operation
36
+
37
+ Raises:
38
+ ValueError: If no task with the given ID exists or if the task is not in PENDING status
39
+ """
40
+ try:
41
+ # Convert id to int if it's a string
42
+ task_id = int(id) if isinstance(id, str) else id
43
+ task = self._task_list.start_task(id=task_id)
44
+ return {
45
+ "id": task.id,
46
+ "description": task.description,
47
+ "status": task.status.value,
48
+ "summary": f"Task '{id}' started successfully"
49
+ }
50
+ except ValueError as e:
51
+ return {
52
+ "error": str(e),
53
+ "summary": f"Failed to start task: {str(e)}"
54
+ }
55
+
56
+ @property
57
+ def descriptor(self):
58
+ """
59
+ Get the descriptor for the tool.
60
+
61
+ Returns:
62
+ The descriptor dictionary
63
+ """
64
+ return {
65
+ "type": "function",
66
+ "function": {
67
+ "name": "start_task",
68
+ "description": "Start a task by changing its status from PENDING to IN_PROGRESS.",
69
+ "parameters": {
70
+ "type": "object",
71
+ "properties": {
72
+ "id": {
73
+ "type": "integer",
74
+ "description": "The ID of the task to start"
75
+ }
76
+ },
77
+ "required": ["id"],
78
+ "additionalProperties": False
79
+ }
80
+ }
81
+ }
@@ -0,0 +1,43 @@
1
+ from unittest.mock import Mock
2
+
3
+ import pytest
4
+
5
+ from mojentic.llm.tools.ephemeral_task_manager.ephemeral_task_list import EphemeralTaskList, Task, TaskStatus
6
+ from mojentic.llm.tools.ephemeral_task_manager.start_task_tool import StartTaskTool
7
+
8
+
9
+ @pytest.fixture
10
+ def mock_task_list():
11
+ mock = Mock(spec=EphemeralTaskList)
12
+ return mock
13
+
14
+
15
+ @pytest.fixture
16
+ def start_task_tool(mock_task_list):
17
+ return StartTaskTool(task_list=mock_task_list)
18
+
19
+
20
+ class DescribeStartTaskTool:
21
+ def should_call_start_task_with_correct_id(self, start_task_tool, mock_task_list):
22
+ mock_task = Task(id=1, description="Test task", status=TaskStatus.IN_PROGRESS)
23
+ mock_task_list.start_task.return_value = mock_task
24
+
25
+ start_task_tool.run(id=1)
26
+
27
+ mock_task_list.start_task.assert_called_once_with(id=1)
28
+
29
+ def should_convert_string_id_to_int(self, start_task_tool, mock_task_list):
30
+ mock_task = Task(id=1, description="Test task", status=TaskStatus.IN_PROGRESS)
31
+ mock_task_list.start_task.return_value = mock_task
32
+
33
+ start_task_tool.run(id="1")
34
+
35
+ mock_task_list.start_task.assert_called_once_with(id=1)
36
+
37
+ def should_handle_error_when_start_task_fails(self, start_task_tool, mock_task_list):
38
+ error_message = "Task '1' cannot be started because it is not in PENDING status"
39
+ mock_task_list.start_task.side_effect = ValueError(error_message)
40
+
41
+ start_task_tool.run(id=1)
42
+
43
+ mock_task_list.start_task.assert_called_once_with(id=1)
@@ -1,7 +1,22 @@
1
+ import json
2
+
3
+ from mojentic.llm.gateways.models import TextContent
4
+
5
+
1
6
  class LLMTool:
2
7
  def run(self, **kwargs):
3
8
  raise NotImplementedError
4
9
 
10
+ def call_tool(self, **kwargs):
11
+ result = self.run(**kwargs)
12
+ if isinstance(result, dict):
13
+ result = json.dumps(result)
14
+ return {
15
+ "content": [
16
+ TextContent(type="text", text=result),
17
+ ]
18
+ }
19
+
5
20
  @property
6
21
  def descriptor(self):
7
22
  raise NotImplementedError
@@ -0,0 +1,68 @@
1
+ import json
2
+ from unittest.mock import Mock
3
+
4
+ import pytest
5
+
6
+ from mojentic.llm.gateways.models import TextContent
7
+ from mojentic.llm.tools.llm_tool import LLMTool
8
+
9
+
10
+ class MockLLMTool(LLMTool):
11
+ """A mock implementation of LLMTool for testing purposes."""
12
+
13
+ def __init__(self, run_result=None):
14
+ self._run_result = run_result
15
+ self._descriptor = {
16
+ "function": {
17
+ "name": "mock_tool",
18
+ "description": "A mock tool for testing"
19
+ }
20
+ }
21
+
22
+ def run(self, **kwargs):
23
+ return self._run_result
24
+
25
+ @property
26
+ def descriptor(self):
27
+ return self._descriptor
28
+
29
+
30
+ @pytest.fixture
31
+ def mock_tool_with_dict_result():
32
+ return MockLLMTool(run_result={"key": "value"})
33
+
34
+
35
+ @pytest.fixture
36
+ def mock_tool_with_string_result():
37
+ return MockLLMTool(run_result="test result")
38
+
39
+
40
+ class DescribeLLMTool:
41
+ class DescribeCallTool:
42
+
43
+ def should_convert_dict_result_to_json_string(self, mock_tool_with_dict_result):
44
+ result = mock_tool_with_dict_result.call_tool()
45
+
46
+ assert "content" in result
47
+ assert isinstance(result["content"], list)
48
+ assert len(result["content"]) == 1
49
+ assert isinstance(result["content"][0], TextContent)
50
+ assert result["content"][0].text == json.dumps({"key": "value"})
51
+
52
+ def should_handle_string_result_directly(self, mock_tool_with_string_result):
53
+ result = mock_tool_with_string_result.call_tool()
54
+
55
+ assert "content" in result
56
+ assert isinstance(result["content"], list)
57
+ assert len(result["content"]) == 1
58
+ assert isinstance(result["content"][0], TextContent)
59
+ assert result["content"][0].text == "test result"
60
+
61
+ def should_pass_kwargs_to_run_method(self):
62
+ mock_run = Mock(return_value="test result")
63
+ tool = MockLLMTool()
64
+ tool.run = mock_run
65
+
66
+ tool.call_tool(param1="value1", param2="value2")
67
+
68
+ mock_run.assert_called_once_with(param1="value1", param2="value2")
@@ -0,0 +1,37 @@
1
+ import json
2
+ import os
3
+
4
+ import serpapi
5
+
6
+ from mojentic.llm.tools.llm_tool import LLMTool
7
+
8
+
9
+ class OrganicWebSearchTool(LLMTool):
10
+ def __init__(self, api_key: str = None):
11
+ self.api_key = api_key or os.getenv("SERPAPI_API_KEY")
12
+
13
+ def run(self, query: str, engine: str = "google", location: str = None, hl: str = "en", gl="ca") -> str:
14
+ results = serpapi.search(q=query, engine=engine, location=location, hl=hl, gl=gl, api_key=self.api_key)
15
+ # Limiting this to the organic results cuts this from 60K to 3K tokens
16
+ return json.dumps(results['organic_results'], indent=2)
17
+
18
+ @property
19
+ def descriptor(self):
20
+ return {
21
+ "type": "function",
22
+ "function": {
23
+ "name": "organic_web_search",
24
+ "description":
25
+ "Search the Internet for information matching the given query and return the organic search results.",
26
+ "parameters": {
27
+ "type": "object",
28
+ "properties": {
29
+ "query": {
30
+ "type": "string",
31
+ "description": "The search query."
32
+ },
33
+ },
34
+ "required": ["query"]
35
+ },
36
+ },
37
+ }
@@ -0,0 +1,27 @@
1
+ from mojentic.llm.tools.llm_tool import LLMTool
2
+
3
+
4
+ class TellUserTool(LLMTool):
5
+ def run(self, message: str) -> str:
6
+ print(f"\n\n\nMESSAGE FROM ASSISTANT:\n{message}")
7
+ return "Message delivered to user."
8
+
9
+ @property
10
+ def descriptor(self):
11
+ return {
12
+ "type": "function",
13
+ "function": {
14
+ "name": "tell_user",
15
+ "description": "Display a message to the user without expecting a response. Use this to send important intermediate information to the user as you work on completing their request.",
16
+ "parameters": {
17
+ "type": "object",
18
+ "properties": {
19
+ "message": {
20
+ "type": "string",
21
+ "description": "The important message you want to display to the user."
22
+ }
23
+ },
24
+ "required": ["message"]
25
+ },
26
+ },
27
+ }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mojentic
3
- Version: 0.5.4
3
+ Version: 0.5.6
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/mojility/mojentic
@@ -1,6 +1,7 @@
1
1
  _examples/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  _examples/broker_as_tool.py,sha256=axLrX9lzQAAxSTCmm1njvOk63EWfVRG3NU6pLiMyYH8,2962
3
- _examples/broker_examples.py,sha256=0byvkckM34pOnJhiddh7Rvfy2zRalBH6DT9ayUDT2OE,2292
3
+ _examples/broker_examples.py,sha256=7tES2KyKc3uigBuxkwOTf5UGhp7nVeVqLhd8fEHSWEc,1901
4
+ _examples/broker_image_examples.py,sha256=8dpZ2RFmRYhJqoeWklzlPxmvj9m4M393452SO_D2bJY,1133
4
5
  _examples/characterize_ollama.py,sha256=_TzPEAoTuB-saTiaypEQAsUpiBeM37l9I5wCMU3GM4E,2521
5
6
  _examples/characterize_openai.py,sha256=JQQNjsHIEegjLAS3uzDmq_Ci_ZqXTqjcoVaC-rS_R_8,564
6
7
  _examples/chat_session.py,sha256=7mLpH4IGQUgyyiY-fYbikDEiR5vEH-V5Z1qtB50d_qg,288
@@ -10,6 +11,7 @@ _examples/current_datetime_tool_example.py,sha256=Ihjwp9svf2rf4WUGOzs6L_rEqc5QhP
10
11
  _examples/design_analysis.py,sha256=66JxvnA065QV__WXpxJX_eTBDan34nGcKvao75UPLlw,1321
11
12
  _examples/embeddings.py,sha256=94DAMsMB35BU98hOfOeOsbqntcequFSdtaStox2hTvk,267
12
13
  _examples/ensures_files_exist.py,sha256=LAwX9YtUZGI6NT254PY7oC5yg6q-b9Q_Dez9gGrabQM,2009
14
+ _examples/ephemeral_task_manager_example.py,sha256=Q1YpLPwDkB-ytIGgCh2eWOr5EJ0FE-osxJ0B0wDlQkY,1491
13
15
  _examples/file_deduplication.py,sha256=jYayx4BCrk1uJwVBkjIXzguLQOWLREi4PBPzoK9LuOU,1665
14
16
  _examples/file_tool.py,sha256=F8xU7JdTScNzEXyGYqK6D_xQ28MbUXXm854WJmJkZo8,2214
15
17
  _examples/image_analysis.py,sha256=Kj49vLQD1DIpvv5P7rir4BqzsVCTgq-tfppqXcYVJkA,503
@@ -27,7 +29,8 @@ _examples/simple_llm_repl.py,sha256=bpk7S1-yQ-oZdRD_0ICV37NQxntgvgjiFD5KdIU40Ig,
27
29
  _examples/simple_structured.py,sha256=9nutIoPNFdtwWCfKkUuvFmsBIzcfhBqlonRWGVYDmJo,1327
28
30
  _examples/simple_tool.py,sha256=9hRo2YZk7NmprTIkLmEyueCbZ0Ls1Ey4l4eDvvgoWy8,1288
29
31
  _examples/solver_chat_session.py,sha256=4mTsgQVJWwujDFX6NUIK6kKr45E09Q4yIkZF-FdoTtg,2148
30
- _examples/streaming.py,sha256=bIK4EnfO_BEwR_TOonnUgVPjxA2-bg8PjyEm-iZgDck,1162
32
+ _examples/streaming.py,sha256=P1CGvm11yi_tojnha2Qmp_OFB5A3T-F5dWIzxEclNhM,1137
33
+ _examples/tell_user_example.py,sha256=gPGS_3KAHUIFsnvkDXX6u1mVqlsB67zsyNdGuEho60o,1274
31
34
  _examples/working_memory.py,sha256=xbCHb6Y0Um6ai5T9fWAX4oQOcCQJDinsn902qm8q48E,1935
32
35
  _examples/react/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
33
36
  _examples/react/formatters.py,sha256=nbgWve0YGKaRY6P4tXV84PYw8YDN4neefiq7mR2I_tI,1065
@@ -59,16 +62,16 @@ mojentic/llm/__init__.py,sha256=mwdPpTRofw7_KSlW6ZQmcM-GSpyISWyI2bxphKpV7A0,180
59
62
  mojentic/llm/chat_session.py,sha256=H2gY0mZYVym8jC69VHsmKaRZ9T87Suyw0-TW5r850nA,3992
60
63
  mojentic/llm/chat_session_spec.py,sha256=8-jj-EHV2WwWuvo3t8I75kSEAYiG1nR-OEwkkLTi_z0,3872
61
64
  mojentic/llm/llm_broker.py,sha256=8dEgqU-cPesPk4-jx36oPnvKxB34bLONbpyAW_2L-es,5884
62
- mojentic/llm/llm_broker_spec.py,sha256=zxOf3n8lXmUsowzlMcC-fRcOj_6wwDf7xIqLIV278nM,6979
65
+ mojentic/llm/llm_broker_spec.py,sha256=40lzmYm_6Zje6z5MQ7_o3gSBThLsNW_l_1mZTUVll6A,5342
63
66
  mojentic/llm/message_composers.py,sha256=Fo9o7UGZOOIYoGI_DyOfP_oMiEiCMQz-zdWdTKtozVk,12108
64
- mojentic/llm/message_composers_spec.py,sha256=IXZ-Gl--1MGbmRkFNxucWTE7OZgLQHDDgw1WqMiZnF0,14762
67
+ mojentic/llm/message_composers_spec.py,sha256=VbaDR-fXWogI5ONSpkzvgPY9Tv9HQX6eEqB8J0ev2jQ,11641
65
68
  mojentic/llm/gateways/__init__.py,sha256=u7hXzngoRw_qbsJeiCH2NQ8vC2hF5DnqcXsfLVVPSSw,104
66
69
  mojentic/llm/gateways/anthropic.py,sha256=SsyNjq9QaXaqiMM43C9fwLp57hpgFtwNPJUnOAYVrtc,1788
67
70
  mojentic/llm/gateways/anthropic_messages_adapter.py,sha256=K6kEZeVt7E1endbGMLsh5l9SxC3Y5dnvbcejVqi_qUs,3003
68
71
  mojentic/llm/gateways/embeddings_gateway.py,sha256=kcOhiyHzOyQgKgwPDQJD5oVvfwk71GsBgMYJOIDv5NU,1347
69
72
  mojentic/llm/gateways/file_gateway.py,sha256=3bZpalSyl_R4016WzCmmjUBDtAgPsmx19eVGv6p1Ufk,1418
70
73
  mojentic/llm/gateways/llm_gateway.py,sha256=5BayP6VuMgMHdAzCFaXLRjRCWh-IOYnaq_s4LZ0_3x4,2559
71
- mojentic/llm/gateways/models.py,sha256=rHoXkaK5FOgWV5X-nkFhqubwk3sUQceJj3rBnxgqB-E,2335
74
+ mojentic/llm/gateways/models.py,sha256=lnGvr3E4C5n15v0aI8Cc0FMOH6GBCrk5_XaEEe3vKkM,3015
72
75
  mojentic/llm/gateways/ollama.py,sha256=629fpZhC0zVCYqj360-PKTT4mQOLec5nzzvfMtS_mLQ,7581
73
76
  mojentic/llm/gateways/ollama_messages_adapter.py,sha256=kUN_p2FyN88_trXMcL-Xsn9xPBU7pGKlJwTUEUCf6G4,1404
74
77
  mojentic/llm/gateways/ollama_messages_adapter_spec.py,sha256=gVRbWDrHOa1EiZ0CkEWe0pGn-GKRqdGb-x56HBQeYSE,4981
@@ -81,19 +84,38 @@ mojentic/llm/registry/llm_registry.py,sha256=beyrgGrkXx5ZckUJzC1nQ461vra0fF6s_qR
81
84
  mojentic/llm/registry/models.py,sha256=XOZ0ElTL5mEicpcUk9lrVr0GRFgR1uFmDm7GGWm7yYg,2043
82
85
  mojentic/llm/registry/populate_registry_from_ollama.py,sha256=YFlnyXW-Htveu8frPEntV-c_84Xoh_WhHGww5IqtPIg,2539
83
86
  mojentic/llm/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
84
- mojentic/llm/tools/ask_user_tool.py,sha256=WrI3uTzIEmr_S5Pl-rmvh2f3O2IIFYfnJ5zeel_59ck,972
87
+ mojentic/llm/tools/ask_user_tool.py,sha256=TiLVq1OttptStwxNvZkxJTRCIohf7SqweB2nT4icFYY,984
85
88
  mojentic/llm/tools/current_datetime.py,sha256=JkIFlBBnvE4CMcgZizqITVTtNfL7zeeLxD54E7oMeC8,1585
86
89
  mojentic/llm/tools/date_resolver.py,sha256=VDxX59PTHo0PstDxaJUo3SF7vkvQoG92bo6j8ABq8y4,2185
87
90
  mojentic/llm/tools/date_resolver_spec.py,sha256=OaRvJyhSN8sgi75euk4E5ImaqUmvQdgZKY8u_NOiPWE,1185
88
91
  mojentic/llm/tools/file_manager.py,sha256=X8Uw4XtdH_Ol2EB3SN11-GYlC1diJ1cAywU9_EuCjCg,3788
89
- mojentic/llm/tools/llm_tool.py,sha256=wU1DNf9DpMtcHhP-YC6_NAn1Frel_Ota6yqgPK2Xsp4,407
92
+ mojentic/llm/tools/llm_tool.py,sha256=i81TNkTiFNMtx-HAGV2bhRrTqoqzdxiPcI0lx05W3A4,745
93
+ mojentic/llm/tools/llm_tool_spec.py,sha256=mDRBXrrNvKh-8ZBq6_AbnU1nqdjtdkP_C2XmztllGQM,2071
94
+ mojentic/llm/tools/organic_web_search.py,sha256=X_WQSSFgeMp5jlm0tnqGOHDIZ2KHDvz3k6GF-XqsuN4,1301
95
+ mojentic/llm/tools/tell_user_tool.py,sha256=bF_PTfF0-skCi_Exw6EPpdfoNUZRJ4MWg-XCe4VYd6s,999
90
96
  mojentic/llm/tools/tool_wrapper.py,sha256=6YZOhckgNsSUc7YK6bKjODjRTwi6wcH9bdcySUDPt3Q,1391
91
97
  mojentic/llm/tools/tool_wrapper_spec.py,sha256=LGqtre-g8SzOy3xtpbMdgTnw2EdYutmFOsMpediE8_0,2543
92
- mojentic/llm/tools/web_search.py,sha256=L1accST2xMhGAkwHCLlIvKihTLiaYxl0NI6IqCJWGCw,1102
98
+ mojentic/llm/tools/ephemeral_task_manager/__init__.py,sha256=npuEwAAks8IZtbQCspAtk1K2kLRVfbfs_o9k1kJIPa4,1193
99
+ mojentic/llm/tools/ephemeral_task_manager/append_task_tool.py,sha256=A1nNF9T6ht-B6WC1CAO1F9T-PGHafwBGvETTMI2RENU,2317
100
+ mojentic/llm/tools/ephemeral_task_manager/append_task_tool_spec.py,sha256=cqJ2HSAgBge3S76-hC6T8Bv1Ox3buWeSdsEpVbMjNPs,1159
101
+ mojentic/llm/tools/ephemeral_task_manager/clear_tasks_tool.py,sha256=GCBGVVlRnYS3llZwMUgNgsKBkZKu4FFTaKTb95F9b10,1476
102
+ mojentic/llm/tools/ephemeral_task_manager/clear_tasks_tool_spec.py,sha256=-MMHdu1e8CVfyDeKIpxfI5wyi26Uob3weDPR9rNPEe0,948
103
+ mojentic/llm/tools/ephemeral_task_manager/complete_task_tool.py,sha256=ZW_7DYRLruErdeuBUBuEfgKgE4Hlf-p5lY3W14D5Au8,2454
104
+ mojentic/llm/tools/ephemeral_task_manager/complete_task_tool_spec.py,sha256=qFTJHwLAASyo89kVGX2ATb-2x2hbkxz9hRALMUsZ8RE,1549
105
+ mojentic/llm/tools/ephemeral_task_manager/ephemeral_task_list.py,sha256=jq37585jnSgIARQ0SgB_PQylSv9qI2_igoyr8ZMHUCc,5430
106
+ mojentic/llm/tools/ephemeral_task_manager/ephemeral_task_list_spec.py,sha256=TmaQCsPoZ7IYSnaRiMj8Y7wuaZEzEuGK1n8aSjZQORg,4740
107
+ mojentic/llm/tools/ephemeral_task_manager/insert_task_after_tool.py,sha256=hoVMu9_-cDYIIrAf66rIPIj_qep1sXd5JbgT4ZfLFdk,2947
108
+ mojentic/llm/tools/ephemeral_task_manager/insert_task_after_tool_spec.py,sha256=8UrjnLlEjF28RLPnsg5CESuSmaVUGULMdUjtYu5KW9w,1791
109
+ mojentic/llm/tools/ephemeral_task_manager/list_tasks_tool.py,sha256=jnkmmxOcytygDDvqEZT8cdqDZCedyC54FI2Gee7igrA,2103
110
+ mojentic/llm/tools/ephemeral_task_manager/list_tasks_tool_spec.py,sha256=xwPAhx5ix7In8NFMm6VVbxoYG1iwLHcn_7wqMHE6HH8,1162
111
+ mojentic/llm/tools/ephemeral_task_manager/prepend_task_tool.py,sha256=GGqPTdBTkjhXMyNcWAJcCkuVBxGB3xmTIyKV9eDmwNA,2349
112
+ mojentic/llm/tools/ephemeral_task_manager/prepend_task_tool_spec.py,sha256=lUCnejAON9g0DDNS64EVHwapPjF8b87RsXPUVvvG0b4,1174
113
+ mojentic/llm/tools/ephemeral_task_manager/start_task_tool.py,sha256=VH8Wa4-ZmkMIsyLuLXJx4pGidiT0KeT55DnujFpK-0o,2414
114
+ mojentic/llm/tools/ephemeral_task_manager/start_task_tool_spec.py,sha256=oDeVPPfquM2ojwG0aaNnbWCB_LRgm8runtG-CumZkLg,1490
93
115
  mojentic/utils/__init__.py,sha256=lqECkkoFvHFttDnafRE1vvh0Dmna_lwupMToP5VvX5k,115
94
116
  mojentic/utils/formatting.py,sha256=bPrwwdluXdQ8TsFxfWtHNOeMWKNvAfABSoUnnA1g7c8,947
95
- mojentic-0.5.4.dist-info/licenses/LICENSE.md,sha256=txSgV8n5zY1W3NiF5HHsCwlaW0e8We1cSC6TuJUqxXA,1060
96
- mojentic-0.5.4.dist-info/METADATA,sha256=nMGgFMtdzLGe0h4j8Ohyl_DnetZnoObcZvhORCXA8Ec,4956
97
- mojentic-0.5.4.dist-info/WHEEL,sha256=SmOxYU7pzNKBqASvQJ7DjX3XGUF92lrGhMb3R6_iiqI,91
98
- mojentic-0.5.4.dist-info/top_level.txt,sha256=Q-BvPQ8Eu1jnEqK8Xkr6A9C8Xa1z38oPZRHuA5MCTqg,19
99
- mojentic-0.5.4.dist-info/RECORD,,
117
+ mojentic-0.5.6.dist-info/licenses/LICENSE.md,sha256=txSgV8n5zY1W3NiF5HHsCwlaW0e8We1cSC6TuJUqxXA,1060
118
+ mojentic-0.5.6.dist-info/METADATA,sha256=4kNiXBHxU0wqwBFCBWww1rmoggWOh1om23j8NMAgei8,4956
119
+ mojentic-0.5.6.dist-info/WHEEL,sha256=DnLRTWE75wApRYVsjgc6wsVswC54sMSJhAEd4xhDpBk,91
120
+ mojentic-0.5.6.dist-info/top_level.txt,sha256=Q-BvPQ8Eu1jnEqK8Xkr6A9C8Xa1z38oPZRHuA5MCTqg,19
121
+ mojentic-0.5.6.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (79.0.1)
2
+ Generator: setuptools (80.4.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5