mito-ai 0.1.50__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.
- mito_ai/__init__.py +114 -0
- mito_ai/_version.py +4 -0
- mito_ai/anthropic_client.py +334 -0
- mito_ai/app_deploy/__init__.py +6 -0
- mito_ai/app_deploy/app_deploy_utils.py +44 -0
- mito_ai/app_deploy/handlers.py +345 -0
- mito_ai/app_deploy/models.py +98 -0
- mito_ai/app_manager/__init__.py +4 -0
- mito_ai/app_manager/handlers.py +167 -0
- mito_ai/app_manager/models.py +71 -0
- mito_ai/app_manager/utils.py +24 -0
- mito_ai/auth/README.md +18 -0
- mito_ai/auth/__init__.py +6 -0
- mito_ai/auth/handlers.py +96 -0
- mito_ai/auth/urls.py +13 -0
- mito_ai/chat_history/handlers.py +63 -0
- mito_ai/chat_history/urls.py +32 -0
- mito_ai/completions/completion_handlers/__init__.py +3 -0
- mito_ai/completions/completion_handlers/agent_auto_error_fixup_handler.py +59 -0
- mito_ai/completions/completion_handlers/agent_execution_handler.py +66 -0
- mito_ai/completions/completion_handlers/chat_completion_handler.py +141 -0
- mito_ai/completions/completion_handlers/code_explain_handler.py +113 -0
- mito_ai/completions/completion_handlers/completion_handler.py +42 -0
- mito_ai/completions/completion_handlers/inline_completer_handler.py +48 -0
- mito_ai/completions/completion_handlers/smart_debug_handler.py +160 -0
- mito_ai/completions/completion_handlers/utils.py +147 -0
- mito_ai/completions/handlers.py +415 -0
- mito_ai/completions/message_history.py +401 -0
- mito_ai/completions/models.py +404 -0
- mito_ai/completions/prompt_builders/__init__.py +3 -0
- mito_ai/completions/prompt_builders/agent_execution_prompt.py +57 -0
- mito_ai/completions/prompt_builders/agent_smart_debug_prompt.py +160 -0
- mito_ai/completions/prompt_builders/agent_system_message.py +472 -0
- mito_ai/completions/prompt_builders/chat_name_prompt.py +15 -0
- mito_ai/completions/prompt_builders/chat_prompt.py +116 -0
- mito_ai/completions/prompt_builders/chat_system_message.py +92 -0
- mito_ai/completions/prompt_builders/explain_code_prompt.py +32 -0
- mito_ai/completions/prompt_builders/inline_completer_prompt.py +197 -0
- mito_ai/completions/prompt_builders/prompt_constants.py +170 -0
- mito_ai/completions/prompt_builders/smart_debug_prompt.py +199 -0
- mito_ai/completions/prompt_builders/utils.py +84 -0
- mito_ai/completions/providers.py +284 -0
- mito_ai/constants.py +63 -0
- mito_ai/db/__init__.py +3 -0
- mito_ai/db/crawlers/__init__.py +6 -0
- mito_ai/db/crawlers/base_crawler.py +61 -0
- mito_ai/db/crawlers/constants.py +43 -0
- mito_ai/db/crawlers/snowflake.py +71 -0
- mito_ai/db/handlers.py +168 -0
- mito_ai/db/models.py +31 -0
- mito_ai/db/urls.py +34 -0
- mito_ai/db/utils.py +185 -0
- mito_ai/docker/mssql/compose.yml +37 -0
- mito_ai/docker/mssql/init/setup.sql +21 -0
- mito_ai/docker/mysql/compose.yml +18 -0
- mito_ai/docker/mysql/init/setup.sql +13 -0
- mito_ai/docker/oracle/compose.yml +17 -0
- mito_ai/docker/oracle/init/setup.sql +20 -0
- mito_ai/docker/postgres/compose.yml +17 -0
- mito_ai/docker/postgres/init/setup.sql +13 -0
- mito_ai/enterprise/__init__.py +3 -0
- mito_ai/enterprise/utils.py +15 -0
- mito_ai/file_uploads/__init__.py +3 -0
- mito_ai/file_uploads/handlers.py +248 -0
- mito_ai/file_uploads/urls.py +21 -0
- mito_ai/gemini_client.py +232 -0
- mito_ai/log/handlers.py +38 -0
- mito_ai/log/urls.py +21 -0
- mito_ai/logger.py +37 -0
- mito_ai/openai_client.py +382 -0
- mito_ai/path_utils.py +70 -0
- mito_ai/rules/handlers.py +44 -0
- mito_ai/rules/urls.py +22 -0
- mito_ai/rules/utils.py +56 -0
- mito_ai/settings/handlers.py +41 -0
- mito_ai/settings/urls.py +20 -0
- mito_ai/settings/utils.py +42 -0
- mito_ai/streamlit_conversion/agent_utils.py +37 -0
- mito_ai/streamlit_conversion/prompts/prompt_constants.py +172 -0
- mito_ai/streamlit_conversion/prompts/prompt_utils.py +10 -0
- mito_ai/streamlit_conversion/prompts/streamlit_app_creation_prompt.py +46 -0
- mito_ai/streamlit_conversion/prompts/streamlit_error_correction_prompt.py +28 -0
- mito_ai/streamlit_conversion/prompts/streamlit_finish_todo_prompt.py +45 -0
- mito_ai/streamlit_conversion/prompts/streamlit_system_prompt.py +56 -0
- mito_ai/streamlit_conversion/prompts/update_existing_app_prompt.py +50 -0
- mito_ai/streamlit_conversion/search_replace_utils.py +94 -0
- mito_ai/streamlit_conversion/streamlit_agent_handler.py +144 -0
- mito_ai/streamlit_conversion/streamlit_utils.py +85 -0
- mito_ai/streamlit_conversion/validate_streamlit_app.py +105 -0
- mito_ai/streamlit_preview/__init__.py +6 -0
- mito_ai/streamlit_preview/handlers.py +111 -0
- mito_ai/streamlit_preview/manager.py +152 -0
- mito_ai/streamlit_preview/urls.py +22 -0
- mito_ai/streamlit_preview/utils.py +29 -0
- mito_ai/tests/__init__.py +3 -0
- mito_ai/tests/chat_history/test_chat_history.py +211 -0
- mito_ai/tests/completions/completion_handlers_utils_test.py +190 -0
- mito_ai/tests/conftest.py +53 -0
- mito_ai/tests/create_agent_system_message_prompt_test.py +22 -0
- mito_ai/tests/data/prompt_lg.py +69 -0
- mito_ai/tests/data/prompt_sm.py +6 -0
- mito_ai/tests/data/prompt_xl.py +13 -0
- mito_ai/tests/data/stock_data.sqlite3 +0 -0
- mito_ai/tests/db/conftest.py +39 -0
- mito_ai/tests/db/connections_test.py +102 -0
- mito_ai/tests/db/mssql_test.py +29 -0
- mito_ai/tests/db/mysql_test.py +29 -0
- mito_ai/tests/db/oracle_test.py +29 -0
- mito_ai/tests/db/postgres_test.py +29 -0
- mito_ai/tests/db/schema_test.py +93 -0
- mito_ai/tests/db/sqlite_test.py +31 -0
- mito_ai/tests/db/test_db_constants.py +61 -0
- mito_ai/tests/deploy_app/test_app_deploy_utils.py +89 -0
- mito_ai/tests/file_uploads/__init__.py +2 -0
- mito_ai/tests/file_uploads/test_handlers.py +282 -0
- mito_ai/tests/message_history/test_generate_short_chat_name.py +120 -0
- mito_ai/tests/message_history/test_message_history_utils.py +469 -0
- mito_ai/tests/open_ai_utils_test.py +152 -0
- mito_ai/tests/performance_test.py +329 -0
- mito_ai/tests/providers/test_anthropic_client.py +447 -0
- mito_ai/tests/providers/test_azure.py +631 -0
- mito_ai/tests/providers/test_capabilities.py +120 -0
- mito_ai/tests/providers/test_gemini_client.py +195 -0
- mito_ai/tests/providers/test_mito_server_utils.py +448 -0
- mito_ai/tests/providers/test_model_resolution.py +130 -0
- mito_ai/tests/providers/test_openai_client.py +57 -0
- mito_ai/tests/providers/test_provider_completion_exception.py +66 -0
- mito_ai/tests/providers/test_provider_limits.py +42 -0
- mito_ai/tests/providers/test_providers.py +382 -0
- mito_ai/tests/providers/test_retry_logic.py +389 -0
- mito_ai/tests/providers/test_stream_mito_server_utils.py +140 -0
- mito_ai/tests/providers/utils.py +85 -0
- mito_ai/tests/rules/conftest.py +26 -0
- mito_ai/tests/rules/rules_test.py +117 -0
- mito_ai/tests/server_limits_test.py +406 -0
- mito_ai/tests/settings/conftest.py +26 -0
- mito_ai/tests/settings/settings_test.py +70 -0
- mito_ai/tests/settings/test_settings_constants.py +9 -0
- mito_ai/tests/streamlit_conversion/__init__.py +3 -0
- mito_ai/tests/streamlit_conversion/test_apply_search_replace.py +240 -0
- mito_ai/tests/streamlit_conversion/test_streamlit_agent_handler.py +246 -0
- mito_ai/tests/streamlit_conversion/test_streamlit_utils.py +193 -0
- mito_ai/tests/streamlit_conversion/test_validate_streamlit_app.py +112 -0
- mito_ai/tests/streamlit_preview/test_streamlit_preview_handler.py +118 -0
- mito_ai/tests/streamlit_preview/test_streamlit_preview_manager.py +292 -0
- mito_ai/tests/test_constants.py +47 -0
- mito_ai/tests/test_telemetry.py +12 -0
- mito_ai/tests/user/__init__.py +2 -0
- mito_ai/tests/user/test_user.py +120 -0
- mito_ai/tests/utils/__init__.py +3 -0
- mito_ai/tests/utils/test_anthropic_utils.py +162 -0
- mito_ai/tests/utils/test_gemini_utils.py +98 -0
- mito_ai/tests/version_check_test.py +169 -0
- mito_ai/user/handlers.py +45 -0
- mito_ai/user/urls.py +21 -0
- mito_ai/utils/__init__.py +3 -0
- mito_ai/utils/anthropic_utils.py +168 -0
- mito_ai/utils/create.py +94 -0
- mito_ai/utils/db.py +74 -0
- mito_ai/utils/error_classes.py +42 -0
- mito_ai/utils/gemini_utils.py +133 -0
- mito_ai/utils/message_history_utils.py +87 -0
- mito_ai/utils/mito_server_utils.py +242 -0
- mito_ai/utils/open_ai_utils.py +200 -0
- mito_ai/utils/provider_utils.py +49 -0
- mito_ai/utils/schema.py +86 -0
- mito_ai/utils/server_limits.py +152 -0
- mito_ai/utils/telemetry_utils.py +480 -0
- mito_ai/utils/utils.py +89 -0
- mito_ai/utils/version_utils.py +94 -0
- mito_ai/utils/websocket_base.py +88 -0
- mito_ai/version_check.py +60 -0
- mito_ai-0.1.50.data/data/etc/jupyter/jupyter_server_config.d/mito_ai.json +7 -0
- mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/build_log.json +728 -0
- mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/package.json +243 -0
- mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/schemas/mito_ai/package.json.orig +238 -0
- mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/schemas/mito_ai/toolbar-buttons.json +37 -0
- mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/static/lib_index_js.8f1845da6bf2b128c049.js +21602 -0
- mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/static/lib_index_js.8f1845da6bf2b128c049.js.map +1 -0
- mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/static/node_modules_process_browser_js.4b128e94d31a81ebd209.js +198 -0
- mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/static/node_modules_process_browser_js.4b128e94d31a81ebd209.js.map +1 -0
- mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/static/remoteEntry.78d3ccb73e7ca1da3aae.js +619 -0
- mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/static/remoteEntry.78d3ccb73e7ca1da3aae.js.map +1 -0
- mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/static/style.js +4 -0
- mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/static/style_index_js.5876024bb17dbd6a3ee6.js +712 -0
- mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/static/style_index_js.5876024bb17dbd6a3ee6.js.map +1 -0
- mito_ai-0.1.50.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 +533 -0
- mito_ai-0.1.50.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 +1 -0
- mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_auth_dist_esm_providers_cognito_tokenProvider_tokenProvider_-72f1c8.a917210f057fcfe224ad.js +6941 -0
- mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_auth_dist_esm_providers_cognito_tokenProvider_tokenProvider_-72f1c8.a917210f057fcfe224ad.js.map +1 -0
- mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_dist_esm_index_mjs.6bac1a8c4cc93f15f6b7.js +1021 -0
- mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_dist_esm_index_mjs.6bac1a8c4cc93f15f6b7.js.map +1 -0
- mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_ui-react_dist_esm_index_mjs.4fcecd65bef9e9847609.js +59698 -0
- mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_ui-react_dist_esm_index_mjs.4fcecd65bef9e9847609.js.map +1 -0
- mito_ai-0.1.50.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 +7440 -0
- mito_ai-0.1.50.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 +1 -0
- mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_semver_index_js.3f6754ac5116d47de76b.js +2792 -0
- mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_semver_index_js.3f6754ac5116d47de76b.js.map +1 -0
- mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_vscode-diff_dist_index_js.ea55f1f9346638aafbcf.js +4859 -0
- mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_vscode-diff_dist_index_js.ea55f1f9346638aafbcf.js.map +1 -0
- mito_ai-0.1.50.dist-info/METADATA +221 -0
- mito_ai-0.1.50.dist-info/RECORD +205 -0
- mito_ai-0.1.50.dist-info/WHEEL +4 -0
- mito_ai-0.1.50.dist-info/entry_points.txt +2 -0
- mito_ai-0.1.50.dist-info/licenses/LICENSE +3 -0
|
@@ -0,0 +1,152 @@
|
|
|
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 Final
|
|
5
|
+
from mito_ai.utils.db import (
|
|
6
|
+
get_chat_completion_count,
|
|
7
|
+
get_autocomplete_count,
|
|
8
|
+
get_first_completion_date,
|
|
9
|
+
get_last_reset_date,
|
|
10
|
+
get_user_field,
|
|
11
|
+
set_user_field
|
|
12
|
+
)
|
|
13
|
+
from mito_ai.utils.schema import (
|
|
14
|
+
UJ_MITO_AI_FIRST_USAGE_DATE,
|
|
15
|
+
UJ_AI_MITO_API_NUM_USAGES,
|
|
16
|
+
UJ_MITO_AI_LAST_RESET_DATE,
|
|
17
|
+
UJ_AI_MITO_AUTOCOMPLETE_NUM_USAGES
|
|
18
|
+
)
|
|
19
|
+
from mito_ai.utils.telemetry_utils import (MITO_SERVER_FREE_TIER_LIMIT_REACHED, log)
|
|
20
|
+
from mito_ai.utils.version_utils import is_pro
|
|
21
|
+
from mito_ai.completions.models import MessageType
|
|
22
|
+
from datetime import datetime, timedelta
|
|
23
|
+
|
|
24
|
+
"""
|
|
25
|
+
IT IS EXPRESSLY AGAINST THE SOFTWARE LICENSE TO MODIFY, BYPASS, OR OTHERWISE
|
|
26
|
+
CIRCUMVENT THE QUOTA LIMITS OF THE FREE TIER. We want to provide users with a
|
|
27
|
+
free tier, but running AI models is expensive, so we need to limit the usage
|
|
28
|
+
or we will no longer be able to provide this free tier.
|
|
29
|
+
"""
|
|
30
|
+
# Monthly chat completions limit for free tier users
|
|
31
|
+
OS_MONTHLY_AI_COMPLETIONS_LIMIT: Final[int] = 150
|
|
32
|
+
|
|
33
|
+
# Monthly autocomplete limit for free tier users
|
|
34
|
+
OS_MONTHLY_AUTOCOMPLETE_LIMIT: Final[int] = 5000
|
|
35
|
+
|
|
36
|
+
def check_mito_server_quota(message_type: MessageType) -> None:
|
|
37
|
+
"""
|
|
38
|
+
Checks if the user has exceeded their Mito server quota. Pro users have no limits.
|
|
39
|
+
Raises PermissionError if the user has exceeded their quota.
|
|
40
|
+
|
|
41
|
+
IT IS EXPRESSLY AGAINST THE SOFTWARE LICENSE TO MODIFY, BYPASS, OR OTHERWISE
|
|
42
|
+
CIRCUMVENT THE QUOTA LIMITS OF THE FREE TIER. We want to provide users with a
|
|
43
|
+
free tier, but running AI models is expensive, so we need to limit the usage
|
|
44
|
+
or we will no longer be able to provide this free tier.
|
|
45
|
+
"""
|
|
46
|
+
if is_pro():
|
|
47
|
+
return
|
|
48
|
+
|
|
49
|
+
# Get current date
|
|
50
|
+
current_date = datetime.now()
|
|
51
|
+
|
|
52
|
+
# Get the date when the last reset occurred
|
|
53
|
+
last_reset_date_str = get_last_reset_date()
|
|
54
|
+
|
|
55
|
+
# If no last reset date is found, set it to today and reset both counters
|
|
56
|
+
if last_reset_date_str is None:
|
|
57
|
+
set_user_field(UJ_MITO_AI_LAST_RESET_DATE, current_date.strftime("%Y-%m-%d"))
|
|
58
|
+
set_user_field(UJ_AI_MITO_API_NUM_USAGES, 0)
|
|
59
|
+
set_user_field(UJ_AI_MITO_AUTOCOMPLETE_NUM_USAGES, 0)
|
|
60
|
+
return
|
|
61
|
+
|
|
62
|
+
# Convert the last reset date string to a datetime object
|
|
63
|
+
last_reset_date = datetime.strptime(last_reset_date_str, "%Y-%m-%d")
|
|
64
|
+
|
|
65
|
+
# Calculate the date one month from the last reset
|
|
66
|
+
one_month_later = last_reset_date + timedelta(days=30) # Approximating a month as 30 days
|
|
67
|
+
|
|
68
|
+
# If it's been more than a month since the last reset, reset both counters
|
|
69
|
+
if current_date >= one_month_later:
|
|
70
|
+
set_user_field(UJ_AI_MITO_API_NUM_USAGES, 0)
|
|
71
|
+
set_user_field(UJ_AI_MITO_AUTOCOMPLETE_NUM_USAGES, 0)
|
|
72
|
+
set_user_field(UJ_MITO_AI_LAST_RESET_DATE, current_date.strftime("%Y-%m-%d"))
|
|
73
|
+
|
|
74
|
+
# Check the appropriate limit based on message type
|
|
75
|
+
if message_type == MessageType.INLINE_COMPLETION:
|
|
76
|
+
# Check autocomplete limit
|
|
77
|
+
autocomplete_count = get_autocomplete_count()
|
|
78
|
+
|
|
79
|
+
if autocomplete_count >= OS_MONTHLY_AUTOCOMPLETE_LIMIT:
|
|
80
|
+
log(MITO_SERVER_FREE_TIER_LIMIT_REACHED)
|
|
81
|
+
raise PermissionError(MITO_SERVER_FREE_TIER_LIMIT_REACHED)
|
|
82
|
+
else:
|
|
83
|
+
# Check chat completion limit
|
|
84
|
+
completion_count = get_chat_completion_count()
|
|
85
|
+
|
|
86
|
+
if completion_count >= OS_MONTHLY_AI_COMPLETIONS_LIMIT:
|
|
87
|
+
log(MITO_SERVER_FREE_TIER_LIMIT_REACHED)
|
|
88
|
+
raise PermissionError(MITO_SERVER_FREE_TIER_LIMIT_REACHED)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def update_mito_server_quota(message_type: MessageType) -> None:
|
|
92
|
+
"""
|
|
93
|
+
Update the user's quota for the Mito Server.
|
|
94
|
+
|
|
95
|
+
IT IS EXPRESSLY AGAINST THE SOFTWARE LICENSE TO MODIFY, BYPASS, OR OTHERWISE
|
|
96
|
+
CIRCUMVENT THE QUOTA LIMITS OF THE FREE TIER. We want to provide users with a
|
|
97
|
+
free tier, but running AI models is expensive, so we need to limit the usage
|
|
98
|
+
or we will no longer be able to provide this free tier.
|
|
99
|
+
"""
|
|
100
|
+
|
|
101
|
+
if message_type == MessageType.CHAT_NAME_GENERATION:
|
|
102
|
+
# We do not count the Chat Name Generation message type towards the quota
|
|
103
|
+
return
|
|
104
|
+
|
|
105
|
+
current_date = datetime.now()
|
|
106
|
+
first_usage_date = get_first_completion_date()
|
|
107
|
+
last_reset_date_str = get_last_reset_date()
|
|
108
|
+
|
|
109
|
+
if first_usage_date is None:
|
|
110
|
+
first_usage_date = current_date.strftime("%Y-%m-%d")
|
|
111
|
+
set_user_field(UJ_MITO_AI_FIRST_USAGE_DATE, first_usage_date)
|
|
112
|
+
|
|
113
|
+
# Initialize the reset date if it doesn't exist
|
|
114
|
+
if last_reset_date_str is None:
|
|
115
|
+
last_reset_date_str = current_date.strftime("%Y-%m-%d")
|
|
116
|
+
set_user_field(UJ_MITO_AI_LAST_RESET_DATE, last_reset_date_str)
|
|
117
|
+
|
|
118
|
+
# Convert the last reset date string to a datetime object
|
|
119
|
+
last_reset_date = datetime.strptime(last_reset_date_str, "%Y-%m-%d")
|
|
120
|
+
|
|
121
|
+
# Calculate the date one month from the last reset
|
|
122
|
+
one_month_later = last_reset_date + timedelta(days=30)
|
|
123
|
+
|
|
124
|
+
# If it's been more than a month since the last reset, reset both counters
|
|
125
|
+
# and make today's date the new reset date
|
|
126
|
+
if current_date >= one_month_later:
|
|
127
|
+
set_user_field(UJ_AI_MITO_API_NUM_USAGES, 0)
|
|
128
|
+
set_user_field(UJ_AI_MITO_AUTOCOMPLETE_NUM_USAGES, 0)
|
|
129
|
+
last_reset_date_str = current_date.strftime("%Y-%m-%d")
|
|
130
|
+
set_user_field(UJ_MITO_AI_LAST_RESET_DATE, last_reset_date_str)
|
|
131
|
+
|
|
132
|
+
# Update the appropriate usage counter based on message type
|
|
133
|
+
if message_type == MessageType.INLINE_COMPLETION:
|
|
134
|
+
# Increment autocomplete count
|
|
135
|
+
autocomplete_count = get_autocomplete_count()
|
|
136
|
+
autocomplete_count = 1 if autocomplete_count is None else autocomplete_count + 1
|
|
137
|
+
|
|
138
|
+
try:
|
|
139
|
+
set_user_field(UJ_AI_MITO_AUTOCOMPLETE_NUM_USAGES, autocomplete_count)
|
|
140
|
+
except Exception as e:
|
|
141
|
+
raise e
|
|
142
|
+
else:
|
|
143
|
+
# Increment chat completion count
|
|
144
|
+
completion_count = get_chat_completion_count()
|
|
145
|
+
completion_count = 1 if completion_count is None else completion_count + 1
|
|
146
|
+
|
|
147
|
+
try:
|
|
148
|
+
set_user_field(UJ_AI_MITO_API_NUM_USAGES, completion_count)
|
|
149
|
+
set_user_field(UJ_MITO_AI_FIRST_USAGE_DATE, first_usage_date)
|
|
150
|
+
except Exception as e:
|
|
151
|
+
raise e
|
|
152
|
+
|
|
@@ -0,0 +1,480 @@
|
|
|
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
|
+
from typing import Any, Dict, Literal, Optional, List
|
|
7
|
+
from mito_ai.utils.version_utils import MITOSHEET_HELPER_PRIVATE, is_pro
|
|
8
|
+
from mito_ai.utils.schema import UJ_AI_MITO_API_NUM_USAGES, UJ_MITOSHEET_TELEMETRY, UJ_STATIC_USER_ID, UJ_USER_EMAIL, UJ_FEEDBACKS_V2
|
|
9
|
+
from mito_ai.utils.db import get_user_field
|
|
10
|
+
from mito_ai._version import __version__
|
|
11
|
+
from mito_ai.utils.utils import is_running_test
|
|
12
|
+
from mito_ai.completions.models import MessageType
|
|
13
|
+
import analytics
|
|
14
|
+
|
|
15
|
+
WRITE_KEY = '6I7ptc5wcIGC4WZ0N1t0NXvvAbjRGUgX'
|
|
16
|
+
analytics.write_key = WRITE_KEY
|
|
17
|
+
|
|
18
|
+
# If you want, you can optionally choose to print logs
|
|
19
|
+
# helpful for debugging.
|
|
20
|
+
PRINT_LOGS = False
|
|
21
|
+
|
|
22
|
+
#################################
|
|
23
|
+
# Mito AI Completion
|
|
24
|
+
# Constants for logging the success or error of Mito AI
|
|
25
|
+
MITO_AI_COMPLETION_SUCCESS = 'mito_ai_success'
|
|
26
|
+
MITO_AI_COMPLETION_ERROR = 'mito_ai_error'
|
|
27
|
+
MITO_AI_COMPLETION_RETRY = 'mito_ai_retry'
|
|
28
|
+
|
|
29
|
+
# Params
|
|
30
|
+
# - logging the type of key
|
|
31
|
+
KEY_TYPE_PARAM = 'AI_key_type'
|
|
32
|
+
MITO_SERVER_KEY: Literal['mito_server_key'] = 'mito_server_key'
|
|
33
|
+
USER_KEY: Literal['user_key'] = 'user_key'
|
|
34
|
+
# - logging if the user is in dev mode
|
|
35
|
+
IS_DEV_MODE_PARAM = 'is_dev_mode'
|
|
36
|
+
|
|
37
|
+
# - logging the number of usages of the Mito server
|
|
38
|
+
MITO_SERVER_NUM_USAGES = 'mito_server_num_usages'
|
|
39
|
+
#################################
|
|
40
|
+
|
|
41
|
+
#################################
|
|
42
|
+
# Mito Server Free Tier Reached
|
|
43
|
+
MITO_SERVER_FREE_TIER_LIMIT_REACHED = 'mito_server_free_tier_limit_reached'
|
|
44
|
+
#################################
|
|
45
|
+
|
|
46
|
+
def is_dev_mode() -> bool:
|
|
47
|
+
"""
|
|
48
|
+
Check if mito-ai is installed in editable/development mode.
|
|
49
|
+
|
|
50
|
+
This function detects editable installs using the modern PEP 660 standard
|
|
51
|
+
(pip >= 21.3). Works for most development scenarios where developers use
|
|
52
|
+
`pip install -e .`
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
bool: True if running in development mode, False otherwise.
|
|
56
|
+
|
|
57
|
+
Limitations:
|
|
58
|
+
- Requires pip >= 21.3 for reliable detection
|
|
59
|
+
- Won't detect manual PYTHONPATH manipulation
|
|
60
|
+
- Won't detect legacy .egg-link installations (very old pip)
|
|
61
|
+
|
|
62
|
+
Note: This is a best-effort detection. For 100% reliability, consider
|
|
63
|
+
also setting a MITO_DEVELOPER_MODE environment variable.
|
|
64
|
+
"""
|
|
65
|
+
try:
|
|
66
|
+
import importlib.metadata
|
|
67
|
+
import json
|
|
68
|
+
|
|
69
|
+
dist = importlib.metadata.distribution('mito-ai')
|
|
70
|
+
direct_url_text = dist.read_text('direct_url.json')
|
|
71
|
+
if direct_url_text:
|
|
72
|
+
direct_url = json.loads(direct_url_text)
|
|
73
|
+
direct_url_dir_info = direct_url.get('dir_info', {})
|
|
74
|
+
editable = direct_url_dir_info.get('editable', None)
|
|
75
|
+
return False if editable is None else editable
|
|
76
|
+
except Exception:
|
|
77
|
+
pass
|
|
78
|
+
|
|
79
|
+
return False
|
|
80
|
+
|
|
81
|
+
def telemetry_turned_on(key_type: Optional[str] = None) -> bool:
|
|
82
|
+
"""
|
|
83
|
+
Helper function that tells you if logging is turned on or
|
|
84
|
+
turned off on the entire Mito instance
|
|
85
|
+
"""
|
|
86
|
+
# If the user is on the Mito server, then they are sending
|
|
87
|
+
# us their information already
|
|
88
|
+
if key_type == 'mito_server_key':
|
|
89
|
+
return True
|
|
90
|
+
|
|
91
|
+
# If private helper is installed, then we don't log anything
|
|
92
|
+
if MITOSHEET_HELPER_PRIVATE:
|
|
93
|
+
return False
|
|
94
|
+
|
|
95
|
+
# TODO: Check if the an enterprise user has turned telemetry to true
|
|
96
|
+
|
|
97
|
+
# If Mito Pro is on, then don't log anything
|
|
98
|
+
if is_pro():
|
|
99
|
+
return False
|
|
100
|
+
|
|
101
|
+
telemetry = get_user_field(UJ_MITOSHEET_TELEMETRY)
|
|
102
|
+
if telemetry is None:
|
|
103
|
+
return False
|
|
104
|
+
|
|
105
|
+
return bool(telemetry)
|
|
106
|
+
|
|
107
|
+
def identify(key_type: Optional[str] = None, is_electron: Optional[bool] = None) -> None:
|
|
108
|
+
"""
|
|
109
|
+
Helper function for identifying a user. We just take
|
|
110
|
+
their python version, mito version, and email.
|
|
111
|
+
"""
|
|
112
|
+
if not telemetry_turned_on(key_type):
|
|
113
|
+
return
|
|
114
|
+
|
|
115
|
+
static_user_id = get_user_field(UJ_STATIC_USER_ID)
|
|
116
|
+
user_email = get_user_field(UJ_USER_EMAIL)
|
|
117
|
+
feedbacks_v2 = get_user_field(UJ_FEEDBACKS_V2)
|
|
118
|
+
|
|
119
|
+
params = {
|
|
120
|
+
'version_mitoai': __version__,
|
|
121
|
+
'email': user_email,
|
|
122
|
+
'is_pro': is_pro(),
|
|
123
|
+
'is_jupyterhub': 'True' if 'JUPYTERHUB_API_URL' in os.environ else 'False',
|
|
124
|
+
'is_mito_jupyterhub': 'True' if os.getenv('MITO_JUPYTERHUB') is not None else 'False',
|
|
125
|
+
IS_DEV_MODE_PARAM: is_dev_mode(),
|
|
126
|
+
UJ_FEEDBACKS_V2: feedbacks_v2
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if is_electron is not None:
|
|
130
|
+
# Only update field when we get info from the client. Don't default to False.
|
|
131
|
+
# becase we are only sending this info to the first completion_handler identify call.
|
|
132
|
+
params['is_mito_desktop'] = is_electron
|
|
133
|
+
|
|
134
|
+
if not is_running_test():
|
|
135
|
+
# TODO: If the user is in JupyterLite, we need to do some extra work.
|
|
136
|
+
# You can see this in the mitosheet package.
|
|
137
|
+
try:
|
|
138
|
+
analytics.identify(static_user_id, params)
|
|
139
|
+
except Exception as e:
|
|
140
|
+
pass
|
|
141
|
+
|
|
142
|
+
def chunk_param(param: str, param_name: str, chunk_size: int=250) -> Dict[str, str]:
|
|
143
|
+
"""
|
|
144
|
+
Split a string into chunks of 250 characters.
|
|
145
|
+
|
|
146
|
+
Args:
|
|
147
|
+
param: The string to be chunked
|
|
148
|
+
param_name: The name of the param to be chunked (used as prefix for the chunked keys)
|
|
149
|
+
chunk_size: The number of characters in each chunk
|
|
150
|
+
|
|
151
|
+
Returns:
|
|
152
|
+
dict: A dictionary with keys 'response_part_1', 'response_part_2', etc.
|
|
153
|
+
"""
|
|
154
|
+
|
|
155
|
+
chunks = {}
|
|
156
|
+
|
|
157
|
+
if not param:
|
|
158
|
+
return {}
|
|
159
|
+
|
|
160
|
+
num_chunks = (len(param) + chunk_size - 1) // chunk_size
|
|
161
|
+
|
|
162
|
+
for i in range(num_chunks):
|
|
163
|
+
start = i * chunk_size
|
|
164
|
+
end = min(start + chunk_size, len(param))
|
|
165
|
+
chunks[f'{param_name}_part_{i + 1}'] = param[start:end]
|
|
166
|
+
|
|
167
|
+
return chunks
|
|
168
|
+
|
|
169
|
+
def log(
|
|
170
|
+
log_event: str,
|
|
171
|
+
params: Optional[Dict[str, Any]]=None,
|
|
172
|
+
error: Optional[BaseException]=None,
|
|
173
|
+
key_type: Optional[Literal['mito_server_key', 'user_key']] = None,
|
|
174
|
+
thread_id: Optional[str] = None
|
|
175
|
+
) -> None:
|
|
176
|
+
"""
|
|
177
|
+
This function is the entry point for all logging.
|
|
178
|
+
|
|
179
|
+
If telemetry is not turned off and we are not running tests,
|
|
180
|
+
we log the ai event
|
|
181
|
+
"""
|
|
182
|
+
final_params: Dict[str, Any] = params or {}
|
|
183
|
+
|
|
184
|
+
# Then, make sure to add the user email
|
|
185
|
+
final_params['email'] = get_user_field(UJ_USER_EMAIL)
|
|
186
|
+
|
|
187
|
+
# Add the error if it exists
|
|
188
|
+
if error is not None:
|
|
189
|
+
final_params['error'] = str(error)
|
|
190
|
+
|
|
191
|
+
if thread_id is not None:
|
|
192
|
+
final_params['thread_id'] = thread_id
|
|
193
|
+
|
|
194
|
+
# Process parameters that need chunking
|
|
195
|
+
params_to_remove = []
|
|
196
|
+
params_to_add = {}
|
|
197
|
+
|
|
198
|
+
for param_name, param_value in final_params.items():
|
|
199
|
+
if isinstance(param_value, str) and len(param_value) > 250:
|
|
200
|
+
# Mark for removal
|
|
201
|
+
params_to_remove.append(param_name)
|
|
202
|
+
# Get chunked parameters
|
|
203
|
+
chunked_params = chunk_param(param_value, param_name)
|
|
204
|
+
params_to_add.update(chunked_params)
|
|
205
|
+
|
|
206
|
+
# Apply the changes
|
|
207
|
+
for param_name in params_to_remove:
|
|
208
|
+
del final_params[param_name]
|
|
209
|
+
final_params.update(params_to_add)
|
|
210
|
+
|
|
211
|
+
# Finally, do the acutal logging. We do not log anything when tests are
|
|
212
|
+
# running, or if telemetry is turned off
|
|
213
|
+
if not is_running_test() and telemetry_turned_on(key_type):
|
|
214
|
+
# TODO: If the user is in JupyterLite, we need to do some extra work.
|
|
215
|
+
# You can see this in the mitosheet package.
|
|
216
|
+
|
|
217
|
+
try:
|
|
218
|
+
analytics.track(
|
|
219
|
+
get_user_field(UJ_STATIC_USER_ID),
|
|
220
|
+
log_event,
|
|
221
|
+
final_params
|
|
222
|
+
)
|
|
223
|
+
except Exception as e:
|
|
224
|
+
pass
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
# If we want to print the logs for debugging reasons, then we print them as well
|
|
228
|
+
if PRINT_LOGS:
|
|
229
|
+
print(
|
|
230
|
+
log_event,
|
|
231
|
+
final_params
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
# TODO: Eventually we want to hook this up to the mito log uploader
|
|
235
|
+
# so enterprises can log usage if they want to.
|
|
236
|
+
|
|
237
|
+
def log_ai_completion_success(
|
|
238
|
+
key_type: Literal['mito_server_key', 'user_key'],
|
|
239
|
+
message_type: MessageType,
|
|
240
|
+
last_message_content: str,
|
|
241
|
+
user_input: str,
|
|
242
|
+
response: Dict[str, Any],
|
|
243
|
+
thread_id: str,
|
|
244
|
+
model: str
|
|
245
|
+
) -> None:
|
|
246
|
+
"""
|
|
247
|
+
Logs AI completion success based on the input location.
|
|
248
|
+
|
|
249
|
+
Args:
|
|
250
|
+
key_type: The type of key that was used to get the AI completion
|
|
251
|
+
message_type: The type of message that was sent to the AI
|
|
252
|
+
last_message_content: The last message sent to the AI
|
|
253
|
+
user_input: The user input that was sent to the AI
|
|
254
|
+
response: The response received from the AI
|
|
255
|
+
thread_id: The thread ID for the conversation
|
|
256
|
+
model: The model that was used to get the AI completion
|
|
257
|
+
"""
|
|
258
|
+
|
|
259
|
+
# Params that every log has
|
|
260
|
+
base_params = {
|
|
261
|
+
KEY_TYPE_PARAM: str(key_type),
|
|
262
|
+
IS_DEV_MODE_PARAM: is_dev_mode(),
|
|
263
|
+
'model': model,
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
try:
|
|
267
|
+
code_cell_input = json.dumps(
|
|
268
|
+
last_message_content.split("Code in the active code cell:")[-1]
|
|
269
|
+
.strip()
|
|
270
|
+
.split("```python")[1]
|
|
271
|
+
.strip()
|
|
272
|
+
.split("```")[0]
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
num_usages = get_user_field(UJ_AI_MITO_API_NUM_USAGES)
|
|
276
|
+
except:
|
|
277
|
+
# Most user prompts will have an associated code cell that serves as the input context.
|
|
278
|
+
# However, types like agent:planning (RIP) do not have a code cell input.
|
|
279
|
+
code_cell_input = ""
|
|
280
|
+
num_usages = -1
|
|
281
|
+
|
|
282
|
+
# Chunk certain params to work around mixpanel's 255 character limit
|
|
283
|
+
code_cell_input_chunks = chunk_param(code_cell_input, "code_cell_input")
|
|
284
|
+
response_chunks = chunk_param(response["completion"], "response")
|
|
285
|
+
|
|
286
|
+
for chunk_key, chunk_value in code_cell_input_chunks.items():
|
|
287
|
+
base_params[chunk_key] = chunk_value
|
|
288
|
+
|
|
289
|
+
for chunk_key, chunk_value in response_chunks.items():
|
|
290
|
+
base_params[chunk_key] = chunk_value
|
|
291
|
+
|
|
292
|
+
# Log number of usages (for mito server)
|
|
293
|
+
if num_usages is not None:
|
|
294
|
+
base_params[MITO_SERVER_NUM_USAGES] = str(num_usages)
|
|
295
|
+
|
|
296
|
+
if message_type == MessageType.SMART_DEBUG:
|
|
297
|
+
error_message = (
|
|
298
|
+
last_message_content.split("Error Message:")[-1]
|
|
299
|
+
.split("ERROR ANALYSIS:")[0]
|
|
300
|
+
.strip()
|
|
301
|
+
)
|
|
302
|
+
error_type = error_message.split(": ")[0]
|
|
303
|
+
|
|
304
|
+
final_params = base_params
|
|
305
|
+
final_params["error_message"] = error_message
|
|
306
|
+
final_params["error_type"] = error_type
|
|
307
|
+
|
|
308
|
+
log("mito_ai_smart_debug_success", params=final_params, key_type=key_type, thread_id=thread_id)
|
|
309
|
+
elif message_type == MessageType.CODE_EXPLAIN:
|
|
310
|
+
final_params = base_params
|
|
311
|
+
|
|
312
|
+
log("mito_ai_code_explain_success", params=final_params, key_type=key_type, thread_id=thread_id)
|
|
313
|
+
elif message_type == MessageType.CHAT:
|
|
314
|
+
final_params = base_params
|
|
315
|
+
|
|
316
|
+
# Chunk the user input
|
|
317
|
+
user_input_chunks = chunk_param(user_input, "user_input")
|
|
318
|
+
|
|
319
|
+
for chunk_key, chunk_value in user_input_chunks.items():
|
|
320
|
+
final_params[chunk_key] = chunk_value
|
|
321
|
+
|
|
322
|
+
log("mito_ai_chat_success", params=final_params, key_type=key_type, thread_id=thread_id)
|
|
323
|
+
elif message_type == MessageType.AGENT_EXECUTION:
|
|
324
|
+
final_params = base_params
|
|
325
|
+
|
|
326
|
+
# Chunk the user input
|
|
327
|
+
user_input_chunks = chunk_param(user_input, "user_input")
|
|
328
|
+
|
|
329
|
+
for chunk_key, chunk_value in user_input_chunks.items():
|
|
330
|
+
final_params[chunk_key] = chunk_value
|
|
331
|
+
|
|
332
|
+
# If the user input is not empty, then this is the user giving the agent a new task
|
|
333
|
+
new_user_input = 'True' if len(user_input_chunks) > 0 else 'False'
|
|
334
|
+
final_params["new_user_input"] = new_user_input
|
|
335
|
+
|
|
336
|
+
log("mito_ai_agent_execution_success", params=final_params, key_type=key_type, thread_id=thread_id)
|
|
337
|
+
elif message_type == MessageType.INLINE_COMPLETION:
|
|
338
|
+
final_params = base_params
|
|
339
|
+
log("mito_ai_inline_completion_success", params=final_params, key_type=key_type, thread_id=thread_id)
|
|
340
|
+
elif message_type == MessageType.AGENT_AUTO_ERROR_FIXUP:
|
|
341
|
+
final_params = base_params
|
|
342
|
+
log("mito_ai_agent_auto_error_fixup_success", params=final_params, key_type=key_type, thread_id=thread_id)
|
|
343
|
+
else:
|
|
344
|
+
final_params = base_params
|
|
345
|
+
final_params["note"] = (
|
|
346
|
+
"This input_location has not been accounted for in `telemetry_utils.py`."
|
|
347
|
+
)
|
|
348
|
+
|
|
349
|
+
log(f"mito_ai_{message_type.value}_success", params=final_params, key_type=key_type, thread_id=thread_id)
|
|
350
|
+
|
|
351
|
+
def log_db_connection_attempt(connection_type: str) -> None:
|
|
352
|
+
log("mito_ai_db_connection_attempt", params={"connection_type": connection_type})
|
|
353
|
+
|
|
354
|
+
def log_db_connection_success(connection_type: str, schema: Dict[str, Any]) -> None:
|
|
355
|
+
log(
|
|
356
|
+
"mito_ai_db_connection_success",
|
|
357
|
+
params={
|
|
358
|
+
"connection_type": connection_type,
|
|
359
|
+
},
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
def log_db_connection_error(connection_type: str, error_message: str) -> None:
|
|
363
|
+
log(
|
|
364
|
+
"mito_ai_db_connection_error",
|
|
365
|
+
params={
|
|
366
|
+
"connection_type": connection_type,
|
|
367
|
+
"error_message": error_message,
|
|
368
|
+
}
|
|
369
|
+
)
|
|
370
|
+
|
|
371
|
+
def log_file_upload_attempt(
|
|
372
|
+
filename: str, file_extension: str, is_chunked: bool, total_chunks: int
|
|
373
|
+
) -> None:
|
|
374
|
+
log(
|
|
375
|
+
"mito_ai_file_upload_attempt",
|
|
376
|
+
params={
|
|
377
|
+
"filename": filename,
|
|
378
|
+
"file_extension": file_extension,
|
|
379
|
+
"is_chunked": is_chunked,
|
|
380
|
+
"total_chunks": total_chunks,
|
|
381
|
+
},
|
|
382
|
+
)
|
|
383
|
+
|
|
384
|
+
def log_file_upload_failure(error: str) -> None:
|
|
385
|
+
log("mito_ai_file_upload_failure", params={"error_message": error})
|
|
386
|
+
|
|
387
|
+
def log_ai_completion_retry(key_type: Literal['mito_server_key', 'user_key'], thread_id: str, message_type: MessageType, error: BaseException) -> None:
|
|
388
|
+
log(MITO_AI_COMPLETION_RETRY, params={KEY_TYPE_PARAM: key_type, "message_type": message_type.value}, thread_id=thread_id, key_type=key_type, error=error)
|
|
389
|
+
|
|
390
|
+
def log_ai_completion_error(
|
|
391
|
+
key_type: Literal['mito_server_key', 'user_key'],
|
|
392
|
+
thread_id: str,
|
|
393
|
+
message_type: MessageType,
|
|
394
|
+
error: BaseException
|
|
395
|
+
) -> None:
|
|
396
|
+
log(MITO_AI_COMPLETION_ERROR, params={KEY_TYPE_PARAM: key_type, "message_type": message_type.value}, thread_id=thread_id, key_type=key_type, error=error)
|
|
397
|
+
|
|
398
|
+
def log_mito_server_free_tier_limit_reached(key_type: Literal['mito_server_key', 'user_key'], message_type: MessageType) -> None:
|
|
399
|
+
log(MITO_SERVER_FREE_TIER_LIMIT_REACHED, params={KEY_TYPE_PARAM: key_type, "message_type": message_type.value}, key_type=key_type)
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
#################################
|
|
403
|
+
# Streamlit Logs
|
|
404
|
+
#################################
|
|
405
|
+
|
|
406
|
+
###
|
|
407
|
+
# Converting Notebook into Streamlit App code
|
|
408
|
+
###
|
|
409
|
+
|
|
410
|
+
def log_streamlit_app_conversion_success(key_type: Literal['mito_server_key', 'user_key'], message_type: MessageType, edit_prompt: str) -> None:
|
|
411
|
+
log(
|
|
412
|
+
"mito_ai_streamlit_app_conversion_success",
|
|
413
|
+
key_type=key_type,
|
|
414
|
+
params={
|
|
415
|
+
"edit_prompt": edit_prompt,
|
|
416
|
+
"message_type": message_type.value
|
|
417
|
+
}
|
|
418
|
+
)
|
|
419
|
+
|
|
420
|
+
def log_streamlit_app_validation_retry(key_type: Literal['mito_server_key', 'user_key'], message_type: MessageType, error: List[str]) -> None:
|
|
421
|
+
log(
|
|
422
|
+
"mito_ai_streamlit_app_conversion_retry",
|
|
423
|
+
params={
|
|
424
|
+
"error_message": error,
|
|
425
|
+
"message_type": message_type.value
|
|
426
|
+
},
|
|
427
|
+
key_type=key_type
|
|
428
|
+
)
|
|
429
|
+
|
|
430
|
+
def log_streamlit_app_conversion_error(key_type: Literal['mito_server_key', 'user_key'], message_type: MessageType, error_message: str, formatted_traceback: str, edit_prompt: str) -> None:
|
|
431
|
+
log(
|
|
432
|
+
"mito_ai_streamlit_app_conversion_error",
|
|
433
|
+
params={
|
|
434
|
+
"error_message": error_message,
|
|
435
|
+
"traceback": formatted_traceback,
|
|
436
|
+
"edit_prompt": edit_prompt,
|
|
437
|
+
"message_type": message_type.value
|
|
438
|
+
},
|
|
439
|
+
key_type=key_type
|
|
440
|
+
)
|
|
441
|
+
|
|
442
|
+
###
|
|
443
|
+
# Setting up Preview
|
|
444
|
+
###
|
|
445
|
+
|
|
446
|
+
def log_streamlit_app_preview_success(key_type: Literal['mito_server_key', 'user_key'], message_type: MessageType, edit_prompt: str) -> None:
|
|
447
|
+
log(
|
|
448
|
+
"mito_ai_streamlit_app_preview_success",
|
|
449
|
+
key_type=key_type,
|
|
450
|
+
params={
|
|
451
|
+
"edit_prompt": edit_prompt,
|
|
452
|
+
"message_type": message_type.value
|
|
453
|
+
}
|
|
454
|
+
)
|
|
455
|
+
|
|
456
|
+
def log_streamlit_app_preview_failure(key_type: Literal['mito_server_key', 'user_key'], message_type: MessageType, error_message: str, formatted_traceback: str, edit_prompt: str) -> None:
|
|
457
|
+
log(
|
|
458
|
+
"mito_ai_streamlit_app_preview_failure",
|
|
459
|
+
key_type=key_type,
|
|
460
|
+
params={
|
|
461
|
+
"error_message": error_message,
|
|
462
|
+
"traceback": formatted_traceback,
|
|
463
|
+
"message_type": message_type.value,
|
|
464
|
+
"edit_prompt": edit_prompt
|
|
465
|
+
}
|
|
466
|
+
)
|
|
467
|
+
|
|
468
|
+
###
|
|
469
|
+
# Deploying Streamlit App
|
|
470
|
+
###
|
|
471
|
+
|
|
472
|
+
def log_streamlit_app_deployment_failure(key_type: Literal['mito_server_key', 'user_key'], message_type: MessageType, error: Dict) -> None:
|
|
473
|
+
log(
|
|
474
|
+
"mito_ai_streamlit_app_deployment_failure",
|
|
475
|
+
key_type=key_type,
|
|
476
|
+
params={
|
|
477
|
+
"error": error, # Contains all details in app_deploy.models.AppDeployError class
|
|
478
|
+
"message_type": message_type.value
|
|
479
|
+
}
|
|
480
|
+
)
|