mito-ai 0.1.44__py3-none-any.whl → 0.1.46__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 (76) hide show
  1. mito_ai/__init__.py +10 -1
  2. mito_ai/_version.py +1 -1
  3. mito_ai/anthropic_client.py +92 -8
  4. mito_ai/app_deploy/app_deploy_utils.py +25 -0
  5. mito_ai/app_deploy/handlers.py +9 -12
  6. mito_ai/app_deploy/models.py +4 -1
  7. mito_ai/chat_history/handlers.py +63 -0
  8. mito_ai/chat_history/urls.py +32 -0
  9. mito_ai/completions/handlers.py +44 -20
  10. mito_ai/completions/models.py +1 -0
  11. mito_ai/completions/prompt_builders/prompt_constants.py +22 -4
  12. mito_ai/constants.py +3 -0
  13. mito_ai/streamlit_conversion/agent_utils.py +148 -30
  14. mito_ai/streamlit_conversion/prompts/prompt_constants.py +147 -24
  15. mito_ai/streamlit_conversion/prompts/streamlit_app_creation_prompt.py +2 -1
  16. mito_ai/streamlit_conversion/prompts/streamlit_error_correction_prompt.py +2 -2
  17. mito_ai/streamlit_conversion/prompts/streamlit_finish_todo_prompt.py +4 -3
  18. mito_ai/streamlit_conversion/prompts/update_existing_app_prompt.py +50 -0
  19. mito_ai/streamlit_conversion/streamlit_agent_handler.py +101 -104
  20. mito_ai/streamlit_conversion/streamlit_system_prompt.py +1 -0
  21. mito_ai/streamlit_conversion/streamlit_utils.py +18 -17
  22. mito_ai/streamlit_conversion/validate_streamlit_app.py +66 -62
  23. mito_ai/streamlit_preview/handlers.py +5 -3
  24. mito_ai/streamlit_preview/utils.py +11 -7
  25. mito_ai/tests/chat_history/test_chat_history.py +211 -0
  26. mito_ai/tests/deploy_app/test_app_deploy_utils.py +71 -0
  27. mito_ai/tests/message_history/test_message_history_utils.py +43 -19
  28. mito_ai/tests/providers/test_anthropic_client.py +180 -8
  29. mito_ai/tests/streamlit_conversion/test_apply_patch_to_text.py +368 -0
  30. mito_ai/tests/streamlit_conversion/test_fix_diff_headers.py +533 -0
  31. mito_ai/tests/streamlit_conversion/test_streamlit_agent_handler.py +71 -158
  32. mito_ai/tests/streamlit_conversion/test_streamlit_utils.py +16 -16
  33. mito_ai/tests/streamlit_conversion/test_validate_streamlit_app.py +16 -28
  34. mito_ai/tests/streamlit_preview/test_streamlit_preview_handler.py +2 -2
  35. mito_ai/tests/user/__init__.py +2 -0
  36. mito_ai/tests/user/test_user.py +120 -0
  37. mito_ai/tests/utils/test_anthropic_utils.py +4 -4
  38. mito_ai/user/handlers.py +33 -0
  39. mito_ai/user/urls.py +21 -0
  40. mito_ai/utils/anthropic_utils.py +15 -21
  41. mito_ai/utils/message_history_utils.py +4 -3
  42. mito_ai/utils/telemetry_utils.py +7 -4
  43. {mito_ai-0.1.44.data → mito_ai-0.1.46.data}/data/share/jupyter/labextensions/mito_ai/build_log.json +100 -100
  44. {mito_ai-0.1.44.data → mito_ai-0.1.46.data}/data/share/jupyter/labextensions/mito_ai/package.json +2 -2
  45. {mito_ai-0.1.44.data → mito_ai-0.1.46.data}/data/share/jupyter/labextensions/mito_ai/schemas/mito_ai/package.json.orig +1 -1
  46. mito_ai-0.1.44.data/data/share/jupyter/labextensions/mito_ai/static/lib_index_js.cf2e3ad2797fbb53826b.js → mito_ai-0.1.46.data/data/share/jupyter/labextensions/mito_ai/static/lib_index_js.20f12766ecd3d430568e.js +1520 -300
  47. mito_ai-0.1.46.data/data/share/jupyter/labextensions/mito_ai/static/lib_index_js.20f12766ecd3d430568e.js.map +1 -0
  48. mito_ai-0.1.44.data/data/share/jupyter/labextensions/mito_ai/static/remoteEntry.5482493d1270f55b7283.js → mito_ai-0.1.46.data/data/share/jupyter/labextensions/mito_ai/static/remoteEntry.54126ab6511271265443.js +18 -18
  49. mito_ai-0.1.44.data/data/share/jupyter/labextensions/mito_ai/static/remoteEntry.5482493d1270f55b7283.js.map → mito_ai-0.1.46.data/data/share/jupyter/labextensions/mito_ai/static/remoteEntry.54126ab6511271265443.js.map +1 -1
  50. {mito_ai-0.1.44.dist-info → mito_ai-0.1.46.dist-info}/METADATA +2 -2
  51. {mito_ai-0.1.44.dist-info → mito_ai-0.1.46.dist-info}/RECORD +75 -63
  52. mito_ai-0.1.44.data/data/share/jupyter/labextensions/mito_ai/static/lib_index_js.cf2e3ad2797fbb53826b.js.map +0 -1
  53. {mito_ai-0.1.44.data → mito_ai-0.1.46.data}/data/etc/jupyter/jupyter_server_config.d/mito_ai.json +0 -0
  54. {mito_ai-0.1.44.data → mito_ai-0.1.46.data}/data/share/jupyter/labextensions/mito_ai/schemas/mito_ai/toolbar-buttons.json +0 -0
  55. {mito_ai-0.1.44.data → mito_ai-0.1.46.data}/data/share/jupyter/labextensions/mito_ai/static/node_modules_process_browser_js.4b128e94d31a81ebd209.js +0 -0
  56. {mito_ai-0.1.44.data → mito_ai-0.1.46.data}/data/share/jupyter/labextensions/mito_ai/static/node_modules_process_browser_js.4b128e94d31a81ebd209.js.map +0 -0
  57. {mito_ai-0.1.44.data → mito_ai-0.1.46.data}/data/share/jupyter/labextensions/mito_ai/static/style.js +0 -0
  58. {mito_ai-0.1.44.data → mito_ai-0.1.46.data}/data/share/jupyter/labextensions/mito_ai/static/style_index_js.5876024bb17dbd6a3ee6.js +0 -0
  59. {mito_ai-0.1.44.data → mito_ai-0.1.46.data}/data/share/jupyter/labextensions/mito_ai/static/style_index_js.5876024bb17dbd6a3ee6.js.map +0 -0
  60. {mito_ai-0.1.44.data → mito_ai-0.1.46.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_auth_dist_esm_providers_cognito_apis_signOut_mjs-node_module-75790d.688c25857e7b81b1740f.js +0 -0
  61. {mito_ai-0.1.44.data → mito_ai-0.1.46.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_auth_dist_esm_providers_cognito_apis_signOut_mjs-node_module-75790d.688c25857e7b81b1740f.js.map +0 -0
  62. {mito_ai-0.1.44.data → mito_ai-0.1.46.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_auth_dist_esm_providers_cognito_tokenProvider_tokenProvider_-72f1c8.a917210f057fcfe224ad.js +0 -0
  63. {mito_ai-0.1.44.data → mito_ai-0.1.46.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_auth_dist_esm_providers_cognito_tokenProvider_tokenProvider_-72f1c8.a917210f057fcfe224ad.js.map +0 -0
  64. {mito_ai-0.1.44.data → mito_ai-0.1.46.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_dist_esm_index_mjs.6bac1a8c4cc93f15f6b7.js +0 -0
  65. {mito_ai-0.1.44.data → mito_ai-0.1.46.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_dist_esm_index_mjs.6bac1a8c4cc93f15f6b7.js.map +0 -0
  66. {mito_ai-0.1.44.data → mito_ai-0.1.46.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_ui-react_dist_esm_index_mjs.4fcecd65bef9e9847609.js +0 -0
  67. {mito_ai-0.1.44.data → mito_ai-0.1.46.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_ui-react_dist_esm_index_mjs.4fcecd65bef9e9847609.js.map +0 -0
  68. {mito_ai-0.1.44.data → mito_ai-0.1.46.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_react-dom_client_js-node_modules_aws-amplify_ui-react_dist_styles_css.b43d4249e4d3dac9ad7b.js +0 -0
  69. {mito_ai-0.1.44.data → mito_ai-0.1.46.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_react-dom_client_js-node_modules_aws-amplify_ui-react_dist_styles_css.b43d4249e4d3dac9ad7b.js.map +0 -0
  70. {mito_ai-0.1.44.data → mito_ai-0.1.46.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_semver_index_js.3f6754ac5116d47de76b.js +0 -0
  71. {mito_ai-0.1.44.data → mito_ai-0.1.46.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_semver_index_js.3f6754ac5116d47de76b.js.map +0 -0
  72. {mito_ai-0.1.44.data → mito_ai-0.1.46.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_vscode-diff_dist_index_js.ea55f1f9346638aafbcf.js +0 -0
  73. {mito_ai-0.1.44.data → mito_ai-0.1.46.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_vscode-diff_dist_index_js.ea55f1f9346638aafbcf.js.map +0 -0
  74. {mito_ai-0.1.44.dist-info → mito_ai-0.1.46.dist-info}/WHEEL +0 -0
  75. {mito_ai-0.1.44.dist-info → mito_ai-0.1.46.dist-info}/entry_points.txt +0 -0
  76. {mito_ai-0.1.44.dist-info → mito_ai-0.1.46.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,120 @@
1
+ # Copyright (c) Saga Inc.
2
+ # Distributed under the terms of the GNU Affero General Public License v3.0 License.
3
+
4
+ import json
5
+ import os
6
+ import requests
7
+ import tempfile
8
+ from unittest.mock import patch
9
+ import pytest
10
+ from mito_ai.tests.conftest import TOKEN
11
+
12
+
13
+ @pytest.fixture
14
+ def mock_user_json():
15
+ """Fixture that creates a temporary user.json file with test data"""
16
+ with tempfile.TemporaryDirectory() as temp_dir:
17
+ # Create the .mito directory
18
+ mito_dir = os.path.join(temp_dir, ".mito")
19
+ os.makedirs(mito_dir, exist_ok=True)
20
+
21
+ # Create a user.json file with test data
22
+ user_json_path = os.path.join(mito_dir, "user.json")
23
+ user_data = {
24
+ "user_email": "test@mail.com",
25
+ "static_user_id": "test_user_123",
26
+ }
27
+
28
+ with open(user_json_path, "w") as f:
29
+ json.dump(user_data, f)
30
+
31
+ yield user_json_path
32
+
33
+
34
+ # --- GET USER KEY ---
35
+
36
+
37
+ def test_get_user_with_mocked_data_success(
38
+ jp_base_url: str, mock_user_json: str
39
+ ) -> None:
40
+ """Test successful GET user endpoint with mocked data"""
41
+ with patch("mito_ai.utils.db.USER_JSON_PATH", mock_user_json):
42
+ response = requests.get(
43
+ jp_base_url + f"/mito-ai/user/user_email",
44
+ headers={"Authorization": f"token {TOKEN}"},
45
+ )
46
+ assert response.status_code == 200
47
+
48
+ response_json = response.json()
49
+ assert response_json["key"] == "user_email"
50
+ assert response_json["value"] == "test@mail.com"
51
+
52
+
53
+ def test_get_user_with_mocked_data_not_found(
54
+ jp_base_url: str, mock_user_json: str
55
+ ) -> None:
56
+ """Test GET user endpoint with mocked data for non-existent key"""
57
+ with patch("mito_ai.utils.db.USER_JSON_PATH", mock_user_json):
58
+ response = requests.get(
59
+ jp_base_url + "/mito-ai/user/non_existent_key",
60
+ headers={"Authorization": f"token {TOKEN}"},
61
+ )
62
+ assert response.status_code == 404
63
+
64
+ response_json = response.json()
65
+ assert (
66
+ response_json["error"] == "User field with key 'non_existent_key' not found"
67
+ )
68
+
69
+
70
+ def test_get_user_with_no_auth(jp_base_url: str) -> None:
71
+ response = requests.get(
72
+ jp_base_url + f"/mito-ai/user/user_email",
73
+ )
74
+ assert response.status_code == 403 # Forbidden
75
+
76
+
77
+ def test_get_user_with_incorrect_auth(jp_base_url: str) -> None:
78
+ response = requests.get(
79
+ jp_base_url + f"/mito-ai/user/user_email",
80
+ headers={"Authorization": f"token incorrect-token"},
81
+ )
82
+ assert response.status_code == 403 # Forbidden
83
+
84
+
85
+ # --- PUT USER KEY ---
86
+
87
+
88
+ def test_put_user_with_mocked_data_success(
89
+ jp_base_url: str, mock_user_json: str
90
+ ) -> None:
91
+ """Test successful PUT user endpoint with mocked data"""
92
+ with patch("mito_ai.utils.db.USER_JSON_PATH", mock_user_json):
93
+ response = requests.put(
94
+ jp_base_url + f"/mito-ai/user/user_email",
95
+ headers={"Authorization": f"token {TOKEN}"},
96
+ json={"value": "jdoe@mail.com"},
97
+ )
98
+ assert response.status_code == 200
99
+
100
+ response_json = response.json()
101
+ assert response_json["status"] == "success"
102
+ assert response_json["key"] == "user_email"
103
+ assert response_json["value"] == "jdoe@mail.com"
104
+
105
+
106
+ def test_put_user_with_no_auth(jp_base_url: str) -> None:
107
+ response = requests.put(
108
+ jp_base_url + f"/mito-ai/user/user_email",
109
+ json={"value": "jdoe@mail.com"},
110
+ )
111
+ assert response.status_code == 403 # Forbidden
112
+
113
+
114
+ def test_put_user_with_incorrect_auth(jp_base_url: str) -> None:
115
+ response = requests.put(
116
+ jp_base_url + f"/mito-ai/user/user_email",
117
+ headers={"Authorization": f"token incorrect-token"},
118
+ json={"value": "jdoe@mail.com"},
119
+ )
120
+ assert response.status_code == 403 # Forbidden
@@ -35,7 +35,7 @@ def test_basic_request_preparation():
35
35
  max_tokens = 100
36
36
  temperature = 0.7
37
37
  # Use NotGiven to ensure system is not included in inner_data
38
- system = anthropic.NotGiven()
38
+ system = anthropic.Omit()
39
39
  messages: List[MessageParam] = [{"role": "user", "content": "Hello"}]
40
40
  message_type = MessageType.CHAT
41
41
 
@@ -106,7 +106,7 @@ def test_tools_and_tool_choice():
106
106
  model="claude-3-sonnet",
107
107
  max_tokens=100,
108
108
  temperature=0.7,
109
- system=anthropic.NotGiven(),
109
+ system=anthropic.Omit(),
110
110
  messages=[{"role": "user", "content": "Hello"}],
111
111
  message_type=MessageType.CHAT,
112
112
  tools=tools,
@@ -124,7 +124,7 @@ def test_stream_parameter():
124
124
  model="claude-3-sonnet",
125
125
  max_tokens=100,
126
126
  temperature=0.7,
127
- system=anthropic.NotGiven(),
127
+ system=anthropic.Omit(),
128
128
  messages=[{"role": "user", "content": "Hello"}],
129
129
  message_type=MessageType.CHAT,
130
130
  tools=None,
@@ -150,7 +150,7 @@ def test_missing_user_info(monkeypatch):
150
150
  model="claude-3-sonnet",
151
151
  max_tokens=100,
152
152
  temperature=0.7,
153
- system=anthropic.NotGiven(),
153
+ system=anthropic.Omit(),
154
154
  messages=[{"role": "user", "content": "Hello"}],
155
155
  message_type=MessageType.CHAT,
156
156
  tools=None,
@@ -0,0 +1,33 @@
1
+ # Copyright (c) Saga Inc.
2
+ # Distributed under the terms of the GNU Affero General Public License v3.0 License.
3
+
4
+ import json
5
+ import tornado
6
+ from jupyter_server.base.handlers import APIHandler
7
+ from mito_ai.utils.db import get_user_field, set_user_field
8
+ from mito_ai.utils.telemetry_utils import identify
9
+
10
+
11
+ class UserHandler(APIHandler):
12
+ """Handler for operations on a specific user"""
13
+
14
+ @tornado.web.authenticated
15
+ def get(self, key: str) -> None:
16
+ value = get_user_field(key)
17
+ if value is None:
18
+ self.set_status(404)
19
+ self.finish(json.dumps({"error": f"User field with key '{key}' not found"}))
20
+ else:
21
+ self.finish(json.dumps({"key": key, "value": value}))
22
+
23
+ @tornado.web.authenticated
24
+ def put(self, key: str) -> None:
25
+ data = json.loads(self.request.body)
26
+ if "value" not in data:
27
+ self.set_status(400)
28
+ self.finish(json.dumps({"error": "Value is required"}))
29
+ return
30
+
31
+ set_user_field(key, data["value"])
32
+ identify() # Log the new user
33
+ self.finish(json.dumps({"status": "success", "key": key, "value": data["value"]}))
mito_ai/user/urls.py ADDED
@@ -0,0 +1,21 @@
1
+ # Copyright (c) Saga Inc.
2
+ # Distributed under the terms of the GNU Affero General Public License v3.0 License.
3
+
4
+ from typing import Any, List, Tuple
5
+ from jupyter_server.utils import url_path_join
6
+ from mito_ai.user.handlers import UserHandler
7
+
8
+
9
+ def get_user_urls(base_url: str) -> List[Tuple[str, Any, dict]]:
10
+ """Get all user related URL patterns.
11
+
12
+ Args:
13
+ base_url: The base URL for the Jupyter server
14
+
15
+ Returns:
16
+ List of (url_pattern, handler_class, handler_kwargs) tuples
17
+ """
18
+ BASE_URL = base_url + "/mito-ai"
19
+ return [
20
+ (url_path_join(BASE_URL, "user/(.*)"), UserHandler, {}),
21
+ ]
@@ -1,23 +1,14 @@
1
1
  # Copyright (c) Saga Inc.
2
2
  # Distributed under the terms of the GNU Affero General Public License v3.0 License.
3
3
 
4
- import asyncio
5
- import json
6
- import time
7
4
  import anthropic
8
- from typing import Any, Dict, List, Optional, Union, AsyncGenerator, Tuple, Callable, cast
9
-
10
- from anthropic.types import MessageParam, Message, TextBlock, ToolUnionParam
5
+ from typing import Any, Dict, List, Optional, Union, AsyncGenerator, Tuple, Callable
6
+ from anthropic.types import MessageParam, TextBlockParam, ToolUnionParam
11
7
  from mito_ai.utils.mito_server_utils import get_response_from_mito_server, stream_response_from_mito_server
12
8
  from mito_ai.utils.provider_utils import does_message_require_fast_model
13
- from openai.types.chat import ChatCompletionMessageParam
14
- from mito_ai.completions.models import AgentResponse, MessageType, ResponseFormatInfo, CompletionReply, CompletionStreamChunk, CompletionItem
9
+ from mito_ai.completions.models import AgentResponse, MessageType, ResponseFormatInfo, CompletionReply, CompletionStreamChunk
15
10
  from mito_ai.utils.schema import UJ_STATIC_USER_ID, UJ_USER_EMAIL
16
11
  from mito_ai.utils.db import get_user_field
17
- from mito_ai.utils.utils import is_running_test
18
- from mito_ai.utils.server_limits import check_mito_server_quota
19
- from .utils import _create_http_client
20
- from tornado.httpclient import AsyncHTTPClient
21
12
  from mito_ai.constants import MITO_ANTHROPIC_URL
22
13
 
23
14
  __user_email: Optional[str] = None
@@ -32,7 +23,7 @@ def _prepare_anthropic_request_data_and_headers(
32
23
  model: Union[str, None],
33
24
  max_tokens: int,
34
25
  temperature: float,
35
- system: Union[str, anthropic.NotGiven],
26
+ system: Union[str, List[TextBlockParam], anthropic.Omit],
36
27
  messages: List[MessageParam],
37
28
  message_type: MessageType,
38
29
  tools: Optional[List[ToolUnionParam]],
@@ -50,10 +41,11 @@ def _prepare_anthropic_request_data_and_headers(
50
41
  "model": model,
51
42
  "max_tokens": max_tokens,
52
43
  "temperature": temperature,
53
- "messages": messages
44
+ "messages": messages,
45
+ "betas": ["context-1m-2025-08-07"]
54
46
  }
55
- # Add system to inner_data only if it is not anthropic.NotGiven
56
- if not isinstance(system, anthropic.NotGiven):
47
+ # Add system to inner_data only if it is not anthropic.Omit
48
+ if not isinstance(system, anthropic.Omit):
57
49
  inner_data["system"] = system
58
50
  if tools:
59
51
  inner_data["tools"] = tools
@@ -76,7 +68,7 @@ async def get_anthropic_completion_from_mito_server(
76
68
  model: Union[str, None],
77
69
  max_tokens: int,
78
70
  temperature: float,
79
- system: Union[str, anthropic.NotGiven],
71
+ system: Union[str, anthropic.Omit],
80
72
  messages: List[MessageParam],
81
73
  tools: Optional[List[ToolUnionParam]],
82
74
  tool_choice: Optional[dict],
@@ -100,7 +92,7 @@ async def stream_anthropic_completion_from_mito_server(
100
92
  model: Union[str, None],
101
93
  max_tokens: int,
102
94
  temperature: float,
103
- system: Union[str, anthropic.NotGiven],
95
+ system: Union[str, List[TextBlockParam], anthropic.Omit],
104
96
  messages: List[MessageParam],
105
97
  stream: bool,
106
98
  message_type: MessageType,
@@ -110,6 +102,7 @@ async def stream_anthropic_completion_from_mito_server(
110
102
  data, headers = _prepare_anthropic_request_data_and_headers(
111
103
  model, max_tokens, temperature, system, messages, message_type, None, None, stream
112
104
  )
105
+
113
106
  # Use the unified streaming function
114
107
  # If the reply_fn and message_id are empty, this function still handles those requests. This is particularly needed for the streamlit dashboard functionality
115
108
  actual_reply_fn = reply_fn if reply_fn is not None else (lambda x: None)
@@ -127,19 +120,20 @@ async def stream_anthropic_completion_from_mito_server(
127
120
  provider_name="Claude",
128
121
  ):
129
122
  yield chunk
130
-
123
+
124
+
131
125
  def get_anthropic_completion_function_params(
132
126
  message_type: MessageType,
133
127
  model: str,
134
128
  messages: List[MessageParam],
135
129
  max_tokens: int,
136
- system: Union[str, anthropic.NotGiven],
130
+ system: Union[str, List[TextBlockParam], anthropic.Omit],
137
131
  temperature: float = 0.0,
138
132
  tools: Optional[List[ToolUnionParam]] = None,
139
133
  tool_choice: Optional[dict] = None,
140
134
  stream: Optional[bool] = None,
141
135
  response_format_info: Optional[ResponseFormatInfo] = None,
142
- ) -> Dict[str, Any]:
136
+ ) -> Dict[str, Any]:
143
137
  """
144
138
  Build the provider_data dict for Anthropic completions, mirroring the OpenAI approach.
145
139
  Only includes fields needed for the Anthropic API.
@@ -3,6 +3,7 @@
3
3
 
4
4
  import re
5
5
  from typing import List
6
+ from mito_ai.constants import MESSAGE_HISTORY_TRIM_THRESHOLD
6
7
  from openai.types.chat import ChatCompletionMessageParam
7
8
  from mito_ai.completions.prompt_builders.prompt_constants import (
8
9
  ACTIVE_CELL_ID_SECTION_HEADING,
@@ -43,18 +44,18 @@ def trim_sections_from_message_content(content: str) -> str:
43
44
  return content
44
45
 
45
46
 
46
- def trim_old_messages(messages: List[ChatCompletionMessageParam], keep_recent: int = 3) -> List[ChatCompletionMessageParam]:
47
+ def trim_old_messages(messages: List[ChatCompletionMessageParam]) -> List[ChatCompletionMessageParam]:
47
48
  """
48
49
  Trims metadata sections from messages that are older than the specified number of recent messages.
49
50
  We do this in order to reduce the token count of the messages, which helps us stay under the token limit for the LLM.
50
51
  """
51
- if len(messages) <= keep_recent:
52
+ if len(messages) <= MESSAGE_HISTORY_TRIM_THRESHOLD:
52
53
  return messages
53
54
 
54
55
  # Process all messages except the keep_recent most recent ones.
55
56
  # Only trim user messages, which is where this metadata lives.
56
57
  # We want to not edit the system messages, as they contain important information / examples.
57
- for i in range(len(messages) - keep_recent):
58
+ for i in range(len(messages) - MESSAGE_HISTORY_TRIM_THRESHOLD):
58
59
  content = messages[i].get("content")
59
60
 
60
61
  is_user_message = messages[i].get("role") == "user"
@@ -386,10 +386,13 @@ def log_mito_server_free_tier_limit_reached(key_type: Literal['mito_server_key',
386
386
  # Streamlit Conversion
387
387
  #################################
388
388
 
389
- def log_streamlit_app_creation_success(key_type: Literal['mito_server_key', 'user_key'], message_type: MessageType) -> None:
389
+ def log_streamlit_app_creation_success(key_type: Literal['mito_server_key', 'user_key'], message_type: MessageType, edit_prompt: str) -> None:
390
390
  log(
391
391
  "mito_ai_streamlit_app_creation_success",
392
- key_type=key_type
392
+ key_type=key_type,
393
+ params={
394
+ "edit_prompt": edit_prompt,
395
+ }
393
396
  )
394
397
 
395
398
  def log_streamlit_app_creation_retry(key_type: Literal['mito_server_key', 'user_key'], message_type: MessageType, error: str) -> None:
@@ -401,12 +404,12 @@ def log_streamlit_app_creation_retry(key_type: Literal['mito_server_key', 'user_
401
404
  key_type=key_type
402
405
  )
403
406
 
404
- def log_streamlit_app_creation_error(key_type: Literal['mito_server_key', 'user_key'], message_type: MessageType, error: str) -> None:
407
+ def log_streamlit_app_creation_error(key_type: Literal['mito_server_key', 'user_key'], message_type: MessageType, error: str, edit_prompt: str) -> None:
405
408
  log(
406
409
  "mito_ai_streamlit_app_creation_error",
407
410
  params={
408
411
  "error_message": error,
412
+ "edit_prompt": edit_prompt,
409
413
  },
410
414
  key_type=key_type
411
415
  )
412
-