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,404 @@
|
|
|
1
|
+
# Copyright (c) Saga Inc.
|
|
2
|
+
# Distributed under the terms of the GNU Affero General Public License v3.0 License.
|
|
3
|
+
|
|
4
|
+
import traceback
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
from typing import List, Literal, Optional, NewType, Dict, Any
|
|
7
|
+
from openai.types.chat import ChatCompletionMessageParam
|
|
8
|
+
from enum import Enum
|
|
9
|
+
from pydantic import BaseModel
|
|
10
|
+
|
|
11
|
+
# The ThreadID is the unique identifier for the chat thread.
|
|
12
|
+
ThreadID = NewType('ThreadID', str)
|
|
13
|
+
|
|
14
|
+
########################################################
|
|
15
|
+
# Agent Response formats
|
|
16
|
+
########################################################
|
|
17
|
+
|
|
18
|
+
class CellUpdate(BaseModel):
|
|
19
|
+
type: Literal['modification', 'new']
|
|
20
|
+
index: Optional[int]
|
|
21
|
+
id: Optional[str]
|
|
22
|
+
code: str
|
|
23
|
+
code_summary: str
|
|
24
|
+
cell_type: Optional[Literal['code', 'markdown']]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
# Using a discriminated Pydantic model doesn't work well with OpenAI's API,
|
|
28
|
+
# so instead we just combine all of the possible response types into a single class
|
|
29
|
+
# for now and rely on the AI to respond with the correct types, following the format
|
|
30
|
+
# that we show it in the system prompt.
|
|
31
|
+
class AgentResponse(BaseModel):
|
|
32
|
+
type: Literal['cell_update', 'get_cell_output', 'run_all_cells', 'finished_task', 'create_streamlit_app', 'edit_streamlit_app']
|
|
33
|
+
message: str
|
|
34
|
+
cell_update: Optional[CellUpdate]
|
|
35
|
+
get_cell_output_cell_id: Optional[str]
|
|
36
|
+
next_steps: Optional[List[str]]
|
|
37
|
+
analysis_assumptions: Optional[List[str]]
|
|
38
|
+
edit_streamlit_app_prompt: Optional[str]
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@dataclass(frozen=True)
|
|
42
|
+
class ResponseFormatInfo():
|
|
43
|
+
name: str
|
|
44
|
+
# Use the type because we are actually just providing the type format, not an actual instance of the format
|
|
45
|
+
format: type[AgentResponse]
|
|
46
|
+
|
|
47
|
+
########################################################
|
|
48
|
+
# Message Types and Metadata
|
|
49
|
+
########################################################
|
|
50
|
+
|
|
51
|
+
class MessageType(Enum):
|
|
52
|
+
"""
|
|
53
|
+
This is all of the different types of messages that we support through the on_message handler.
|
|
54
|
+
"""
|
|
55
|
+
CHAT = "chat"
|
|
56
|
+
SMART_DEBUG = "smartDebug"
|
|
57
|
+
CODE_EXPLAIN = "codeExplain"
|
|
58
|
+
AGENT_EXECUTION = "agent:execution"
|
|
59
|
+
AGENT_AUTO_ERROR_FIXUP = "agent:autoErrorFixup"
|
|
60
|
+
INLINE_COMPLETION = "inline_completion"
|
|
61
|
+
CHAT_NAME_GENERATION = "chat_name_generation"
|
|
62
|
+
START_NEW_CHAT = "start_new_chat"
|
|
63
|
+
FETCH_HISTORY = "fetch_history"
|
|
64
|
+
GET_THREADS = "get_threads"
|
|
65
|
+
DELETE_THREAD = "delete_thread"
|
|
66
|
+
UPDATE_MODEL_CONFIG = "update_model_config"
|
|
67
|
+
STREAMLIT_CONVERSION = "streamlit_conversion"
|
|
68
|
+
STOP_AGENT = "stop_agent"
|
|
69
|
+
DEPLOY_APP = "deploy_app"
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@dataclass(frozen=True)
|
|
73
|
+
class AIOptimizedCell():
|
|
74
|
+
cell_type: str
|
|
75
|
+
id: str
|
|
76
|
+
code: str
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
@dataclass(frozen=True)
|
|
80
|
+
class ChatMessageMetadata():
|
|
81
|
+
promptType: Literal['chat']
|
|
82
|
+
threadId: ThreadID
|
|
83
|
+
input: str
|
|
84
|
+
activeCellCode: str
|
|
85
|
+
activeCellId: str
|
|
86
|
+
variables: Optional[List[str]] = None
|
|
87
|
+
files: Optional[List[str]] = None
|
|
88
|
+
base64EncodedActiveCellOutput: Optional[str] = None
|
|
89
|
+
index: Optional[int] = None
|
|
90
|
+
stream: bool = False
|
|
91
|
+
additionalContext: Optional[List[Dict[str, str]]] = None
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
@dataclass(frozen=True)
|
|
95
|
+
class AgentExecutionMetadata():
|
|
96
|
+
promptType: Literal['agent:execution']
|
|
97
|
+
threadId: ThreadID
|
|
98
|
+
input: str
|
|
99
|
+
aiOptimizedCells: List[AIOptimizedCell]
|
|
100
|
+
activeCellId: str
|
|
101
|
+
isChromeBrowser: bool
|
|
102
|
+
notebookPath: str
|
|
103
|
+
notebookID: str
|
|
104
|
+
base64EncodedActiveCellOutput: Optional[str] = None
|
|
105
|
+
variables: Optional[List[str]] = None
|
|
106
|
+
files: Optional[List[str]] = None
|
|
107
|
+
index: Optional[int] = None
|
|
108
|
+
additionalContext: Optional[List[Dict[str, str]]] = None
|
|
109
|
+
|
|
110
|
+
@dataclass(frozen=True)
|
|
111
|
+
class AgentSmartDebugMetadata():
|
|
112
|
+
promptType: Literal['agent:autoErrorFixup']
|
|
113
|
+
threadId: ThreadID
|
|
114
|
+
aiOptimizedCells: List[AIOptimizedCell]
|
|
115
|
+
errorMessage: str
|
|
116
|
+
error_message_producing_code_cell_id: str
|
|
117
|
+
isChromeBrowser: bool
|
|
118
|
+
variables: Optional[List[str]] = None
|
|
119
|
+
files: Optional[List[str]] = None
|
|
120
|
+
|
|
121
|
+
@dataclass(frozen=True)
|
|
122
|
+
class SmartDebugMetadata():
|
|
123
|
+
promptType: Literal['smartDebug']
|
|
124
|
+
threadId: ThreadID
|
|
125
|
+
errorMessage: str
|
|
126
|
+
activeCellCode: str
|
|
127
|
+
activeCellId: str
|
|
128
|
+
variables: Optional[List[str]] = None
|
|
129
|
+
files: Optional[List[str]] = None
|
|
130
|
+
|
|
131
|
+
@dataclass(frozen=True)
|
|
132
|
+
class CodeExplainMetadata():
|
|
133
|
+
promptType: Literal['codeExplain']
|
|
134
|
+
threadId: ThreadID
|
|
135
|
+
variables: Optional[List[str]] = None
|
|
136
|
+
activeCellCode: Optional[str] = None
|
|
137
|
+
|
|
138
|
+
@dataclass(frozen=True)
|
|
139
|
+
class InlineCompleterMetadata():
|
|
140
|
+
promptType: Literal['inline_completion']
|
|
141
|
+
prefix: str
|
|
142
|
+
suffix: str
|
|
143
|
+
variables: Optional[List[str]] = None
|
|
144
|
+
files: Optional[List[str]] = None
|
|
145
|
+
|
|
146
|
+
@dataclass(frozen=True)
|
|
147
|
+
class CompletionRequest:
|
|
148
|
+
"""
|
|
149
|
+
Message send by the client to request an AI chat response.
|
|
150
|
+
"""
|
|
151
|
+
|
|
152
|
+
# Message type.
|
|
153
|
+
type: MessageType
|
|
154
|
+
|
|
155
|
+
# Message UID generated by the client.
|
|
156
|
+
message_id: str
|
|
157
|
+
|
|
158
|
+
# Chat messages.
|
|
159
|
+
messages: List[ChatCompletionMessageParam] = field(default_factory=list)
|
|
160
|
+
|
|
161
|
+
# Whether to stream the response (if supported by the model).
|
|
162
|
+
stream: bool = False
|
|
163
|
+
|
|
164
|
+
# Environment information from the client
|
|
165
|
+
environment: Optional[Dict[str, Any]] = None
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
@dataclass(frozen=True)
|
|
169
|
+
class AICapabilities:
|
|
170
|
+
"""
|
|
171
|
+
AI provider capabilities
|
|
172
|
+
"""
|
|
173
|
+
|
|
174
|
+
# Configuration schema.
|
|
175
|
+
configuration: dict
|
|
176
|
+
|
|
177
|
+
# AI provider name.
|
|
178
|
+
provider: str
|
|
179
|
+
|
|
180
|
+
# Message type.
|
|
181
|
+
type: str = "ai_capabilities"
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
@dataclass(frozen=True)
|
|
185
|
+
class CompletionItemError:
|
|
186
|
+
"""
|
|
187
|
+
Completion item error information.
|
|
188
|
+
"""
|
|
189
|
+
|
|
190
|
+
# Error message.
|
|
191
|
+
message: Optional[str] = None
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
@dataclass(frozen=True)
|
|
195
|
+
class CompletionItem:
|
|
196
|
+
"""
|
|
197
|
+
A completion suggestion.
|
|
198
|
+
"""
|
|
199
|
+
|
|
200
|
+
# The completion.
|
|
201
|
+
content: str
|
|
202
|
+
|
|
203
|
+
# Whether the completion is incomplete or not.
|
|
204
|
+
isIncomplete: Optional[bool] = None
|
|
205
|
+
|
|
206
|
+
# Unique token identifying the completion request in the frontend.
|
|
207
|
+
token: Optional[str] = None
|
|
208
|
+
|
|
209
|
+
# Error information for the completion item.
|
|
210
|
+
error: Optional[CompletionItemError] = None
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
@dataclass(frozen=True)
|
|
214
|
+
class CompletionError:
|
|
215
|
+
"""
|
|
216
|
+
Completion error description.
|
|
217
|
+
"""
|
|
218
|
+
|
|
219
|
+
# Error type.
|
|
220
|
+
error_type: str
|
|
221
|
+
|
|
222
|
+
# Error title.
|
|
223
|
+
title: str
|
|
224
|
+
|
|
225
|
+
# Error traceback.
|
|
226
|
+
traceback: str
|
|
227
|
+
|
|
228
|
+
# Hint to resolve the error.
|
|
229
|
+
hint: str = ""
|
|
230
|
+
|
|
231
|
+
@staticmethod
|
|
232
|
+
def from_exception(exception: BaseException, hint: str = "") -> "CompletionError":
|
|
233
|
+
"""
|
|
234
|
+
Create a completion error from an exception.
|
|
235
|
+
|
|
236
|
+
Note: OpenAI exceptions can include a 'body' attribute with detailed error information.
|
|
237
|
+
While mypy doesn't know about this attribute on BaseException, we need to handle it
|
|
238
|
+
to properly extract error messages from OpenAI API responses.
|
|
239
|
+
"""
|
|
240
|
+
from mito_ai.utils.mito_server_utils import ProviderCompletionException
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
# Handle ProviderCompletionException specially
|
|
244
|
+
if isinstance(exception, ProviderCompletionException):
|
|
245
|
+
return CompletionError(
|
|
246
|
+
error_type="LLM Provider Error",
|
|
247
|
+
title=exception.user_friendly_title,
|
|
248
|
+
traceback=traceback.format_exc(),
|
|
249
|
+
hint=exception.user_friendly_hint
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
# Handle all other exceptions as before
|
|
253
|
+
error_type = type(exception)
|
|
254
|
+
error_module = getattr(error_type, "__module__", "")
|
|
255
|
+
|
|
256
|
+
# Handle OpenAI exceptions that have a 'body' attribute
|
|
257
|
+
title = ""
|
|
258
|
+
body = getattr(exception, "body", None)
|
|
259
|
+
if body and hasattr(body, "get"):
|
|
260
|
+
title = body.get("message", "")
|
|
261
|
+
|
|
262
|
+
if not title and exception.args:
|
|
263
|
+
title = exception.args[0]
|
|
264
|
+
|
|
265
|
+
if not title:
|
|
266
|
+
title = "Exception"
|
|
267
|
+
|
|
268
|
+
return CompletionError(
|
|
269
|
+
error_type=f"{error_module}.{error_type.__name__}"
|
|
270
|
+
if error_module
|
|
271
|
+
else error_type.__name__,
|
|
272
|
+
title=title,
|
|
273
|
+
traceback=traceback.format_exc(),
|
|
274
|
+
hint=hint,
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
@dataclass(frozen=True)
|
|
278
|
+
class ErrorMessage(CompletionError):
|
|
279
|
+
"""
|
|
280
|
+
Error message.
|
|
281
|
+
"""
|
|
282
|
+
|
|
283
|
+
# Message type.
|
|
284
|
+
type: Literal["error"] = "error"
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
@dataclass(frozen=True)
|
|
289
|
+
class CompletionReply:
|
|
290
|
+
"""
|
|
291
|
+
Message sent from model to client with the completion suggestions.
|
|
292
|
+
"""
|
|
293
|
+
|
|
294
|
+
# List of completion items.
|
|
295
|
+
items: List[CompletionItem]
|
|
296
|
+
|
|
297
|
+
# Parent message UID.
|
|
298
|
+
parent_id: str
|
|
299
|
+
|
|
300
|
+
# Message type.
|
|
301
|
+
type: Literal["reply"] = "reply"
|
|
302
|
+
|
|
303
|
+
# Completion error.
|
|
304
|
+
error: Optional[CompletionError] = None
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
@dataclass(frozen=True)
|
|
308
|
+
class CompletionStreamChunk:
|
|
309
|
+
"""
|
|
310
|
+
Message sent from model to client with the infill suggestions
|
|
311
|
+
"""
|
|
312
|
+
|
|
313
|
+
chunk: CompletionItem
|
|
314
|
+
|
|
315
|
+
# Parent message UID.
|
|
316
|
+
parent_id: str
|
|
317
|
+
|
|
318
|
+
# Whether the completion is done or not.
|
|
319
|
+
done: bool
|
|
320
|
+
|
|
321
|
+
# Message type.
|
|
322
|
+
type: Literal["chunk"] = "chunk"
|
|
323
|
+
|
|
324
|
+
# Completion error.
|
|
325
|
+
error: Optional[CompletionError] = None
|
|
326
|
+
"""Completion error."""
|
|
327
|
+
|
|
328
|
+
@dataclass(frozen=True)
|
|
329
|
+
class FetchHistoryReply:
|
|
330
|
+
"""
|
|
331
|
+
Message sent from model to client with the chat history.
|
|
332
|
+
"""
|
|
333
|
+
|
|
334
|
+
# Message UID.
|
|
335
|
+
parent_id: str
|
|
336
|
+
|
|
337
|
+
# List of chat messages.
|
|
338
|
+
items: List[ChatCompletionMessageParam]
|
|
339
|
+
|
|
340
|
+
# Message type.
|
|
341
|
+
type: Literal["reply"] = "reply"
|
|
342
|
+
|
|
343
|
+
@dataclass(frozen=True)
|
|
344
|
+
class ChatThreadMetadata:
|
|
345
|
+
"""
|
|
346
|
+
Chat thread item.
|
|
347
|
+
"""
|
|
348
|
+
|
|
349
|
+
thread_id: ThreadID
|
|
350
|
+
|
|
351
|
+
name: str
|
|
352
|
+
|
|
353
|
+
creation_ts: float
|
|
354
|
+
|
|
355
|
+
last_interaction_ts: float
|
|
356
|
+
|
|
357
|
+
@dataclass(frozen=True)
|
|
358
|
+
class StartNewChatReply:
|
|
359
|
+
"""
|
|
360
|
+
Message sent from model to client after starting a new chat thread.
|
|
361
|
+
"""
|
|
362
|
+
|
|
363
|
+
# Message UID.
|
|
364
|
+
parent_id: str
|
|
365
|
+
|
|
366
|
+
# Chat thread item.
|
|
367
|
+
thread_id: ThreadID
|
|
368
|
+
|
|
369
|
+
# Message type.
|
|
370
|
+
type: Literal["reply"] = "reply"
|
|
371
|
+
|
|
372
|
+
@dataclass(frozen=True)
|
|
373
|
+
class FetchThreadsReply:
|
|
374
|
+
"""
|
|
375
|
+
Message sent from model to client with the chat threads.
|
|
376
|
+
"""
|
|
377
|
+
|
|
378
|
+
# Message UID.
|
|
379
|
+
parent_id: str
|
|
380
|
+
|
|
381
|
+
# List of chat threads.
|
|
382
|
+
threads: List[ChatThreadMetadata]
|
|
383
|
+
|
|
384
|
+
# Message type.
|
|
385
|
+
type: Literal["reply"] = "reply"
|
|
386
|
+
|
|
387
|
+
@dataclass(frozen=True)
|
|
388
|
+
class DeleteThreadReply:
|
|
389
|
+
"""
|
|
390
|
+
Message sent from model to client after deleting a chat thread.
|
|
391
|
+
"""
|
|
392
|
+
|
|
393
|
+
# Message UID.
|
|
394
|
+
parent_id: str
|
|
395
|
+
|
|
396
|
+
#Success message
|
|
397
|
+
success: bool
|
|
398
|
+
|
|
399
|
+
# Message type.
|
|
400
|
+
type: Literal["reply"] = "reply"
|
|
401
|
+
|
|
402
|
+
@dataclass(frozen=True)
|
|
403
|
+
class UpdateModelConfigMetadata:
|
|
404
|
+
model: str
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Copyright (c) Saga Inc.
|
|
2
|
+
# Distributed under the terms of the GNU Affero General Public License v3.0 License.
|
|
3
|
+
|
|
4
|
+
from mito_ai.completions.models import AgentExecutionMetadata
|
|
5
|
+
from mito_ai.completions.prompt_builders.prompt_constants import (
|
|
6
|
+
ACTIVE_CELL_ID_SECTION_HEADING,
|
|
7
|
+
FILES_SECTION_HEADING,
|
|
8
|
+
JUPYTER_NOTEBOOK_SECTION_HEADING,
|
|
9
|
+
STREAMLIT_APP_STATUS_SECTION_HEADING,
|
|
10
|
+
VARIABLES_SECTION_HEADING,
|
|
11
|
+
cell_update_output_str
|
|
12
|
+
)
|
|
13
|
+
from mito_ai.completions.prompt_builders.utils import (
|
|
14
|
+
get_rules_str,
|
|
15
|
+
get_selected_context_str,
|
|
16
|
+
get_streamlit_app_status_str
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def create_agent_execution_prompt(md: AgentExecutionMetadata) -> str:
|
|
21
|
+
variables_str = '\n'.join([f"{variable}" for variable in md.variables or []])
|
|
22
|
+
files_str = '\n'.join([f"{file}" for file in md.files or []])
|
|
23
|
+
ai_optimized_cells_str = '\n'.join([f"{cell}" for cell in md.aiOptimizedCells or []])
|
|
24
|
+
rules_str = get_rules_str(md.additionalContext)
|
|
25
|
+
selected_context_str = get_selected_context_str(md.additionalContext)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
streamlit_status_str = get_streamlit_app_status_str(md.notebookID, md.notebookPath)
|
|
29
|
+
|
|
30
|
+
context_str = f"""Remember to choose the correct tool to respond with.
|
|
31
|
+
|
|
32
|
+
{rules_str}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
{JUPYTER_NOTEBOOK_SECTION_HEADING}
|
|
36
|
+
{ai_optimized_cells_str}
|
|
37
|
+
|
|
38
|
+
{VARIABLES_SECTION_HEADING}
|
|
39
|
+
{variables_str}
|
|
40
|
+
|
|
41
|
+
{FILES_SECTION_HEADING}
|
|
42
|
+
{files_str}
|
|
43
|
+
|
|
44
|
+
{STREAMLIT_APP_STATUS_SECTION_HEADING}
|
|
45
|
+
{streamlit_status_str}
|
|
46
|
+
|
|
47
|
+
{ACTIVE_CELL_ID_SECTION_HEADING}
|
|
48
|
+
{md.activeCellId}
|
|
49
|
+
|
|
50
|
+
{selected_context_str}
|
|
51
|
+
|
|
52
|
+
{cell_update_output_str(md.base64EncodedActiveCellOutput is not None)}"""
|
|
53
|
+
|
|
54
|
+
task_str = '' if md.input == '' else f"""Your task:
|
|
55
|
+
{md.input}"""
|
|
56
|
+
|
|
57
|
+
return '\n\n'.join([context_str, task_str]).strip()
|
|
@@ -0,0 +1,160 @@
|
|
|
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 List
|
|
5
|
+
from mito_ai.completions.models import AgentSmartDebugMetadata
|
|
6
|
+
from mito_ai.completions.prompt_builders.prompt_constants import (
|
|
7
|
+
FILES_SECTION_HEADING,
|
|
8
|
+
JUPYTER_NOTEBOOK_SECTION_HEADING,
|
|
9
|
+
VARIABLES_SECTION_HEADING
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
# TODO:
|
|
13
|
+
# 1. In the future, it might make sense to pass the previous CELL_UPDATE to this prompt?
|
|
14
|
+
# 2. In the future, we should let the agent fix up the error by updating a different cell. This is sometimes a better solution.
|
|
15
|
+
# However, to do this, we then need to know which code cells to run in order to validate the update is correct! If the error was
|
|
16
|
+
# produced by code cell 3, and the agent corrects the source of the error in code cell 2, we then need to run cell 2 and 3 to validate
|
|
17
|
+
# the cell update worked properly. This could be many cells if there are intermediate cells. It might require something like a dependency
|
|
18
|
+
# graph of cells that we calculate ourselves, not relying on the AI.
|
|
19
|
+
|
|
20
|
+
def create_agent_smart_debug_prompt(md: AgentSmartDebugMetadata) -> str:
|
|
21
|
+
variables_str = '\n'.join([f"{variable}" for variable in md.variables or []])
|
|
22
|
+
files_str = '\n'.join([f"{file}" for file in md.files or []])
|
|
23
|
+
ai_optimized_cells_str = '\n'.join([f"{cell}" for cell in md.aiOptimizedCells or []])
|
|
24
|
+
|
|
25
|
+
return f"""I just applied and executed the CELL_UPDATE that you just shared with me, but it errored. Below I am sharing with you a strategy for how I want you to resolve this error and information about the actual error that occured.
|
|
26
|
+
|
|
27
|
+
Use this strategy for this message only. After this message, continue using the original set of instructions that I provided you.
|
|
28
|
+
|
|
29
|
+
It is very important that When fixing this error, you do not change the original intent of the code cell.
|
|
30
|
+
|
|
31
|
+
To fix this error, take the following approach:
|
|
32
|
+
Step 1: ERROR ANALYSIS: Analyze the error message to identify why the code cell errored.
|
|
33
|
+
Step 2: INTENT PRESERVATION: Make sure you understand the intent of the CELL_UPDATE so that you can be sure to preserve it when you create a new CELL_UPDATE
|
|
34
|
+
Step 3: ERROR CORRECTION: Respond with a new CELL_UPDATE that is applied to the same cell as the erroring CELL_UPDATE.
|
|
35
|
+
|
|
36
|
+
<Instructions for each Phase />
|
|
37
|
+
|
|
38
|
+
ERROR ANALYSIS:
|
|
39
|
+
|
|
40
|
+
- Identify error type (Syntax, Runtime, Logic).
|
|
41
|
+
- Use the defined variables and Jupyter Notebook to understand the error.
|
|
42
|
+
- Consider kernel state and execution order
|
|
43
|
+
|
|
44
|
+
INTENT PRESERVATION:
|
|
45
|
+
|
|
46
|
+
- Try to understand the user's intent using the defined variables and the Jupyter Notebook
|
|
47
|
+
|
|
48
|
+
ERROR CORRECTION:
|
|
49
|
+
|
|
50
|
+
- Return the full, updated version of cell {md.error_message_producing_code_cell_id} with the error fixed and a short explanation of the error.
|
|
51
|
+
- You can only update code in {md.error_message_producing_code_cell_id}. You are unable to edit the code in any other cell when resolving this error.
|
|
52
|
+
- Propose a solution that fixes the error and does not change the user's intent.
|
|
53
|
+
- Make the solution as simple as possible.
|
|
54
|
+
- Reuse as much of the existing code as possible.
|
|
55
|
+
- DO NOT ADD TEMPORARY COMMENTS like '# Fixed the typo here' or '# Added this line to fix the error'
|
|
56
|
+
- If you encounter a ModuleNotFoundError, you can install the package by adding the the following line to the top of the code cell: `!pip install <package_name> --quiet`.
|
|
57
|
+
- If you encounter a NameError, you can use the RUN_ALL_CELLS tool to run all cells from the top of the notebook to the bottom to bring the variable into scope.
|
|
58
|
+
RUN_ALL_CELLS:
|
|
59
|
+
When you want to execute all cells in the notebook from top to bottom, respond with this format:
|
|
60
|
+
{{
|
|
61
|
+
type: 'run_all_cells',
|
|
62
|
+
message: str
|
|
63
|
+
}}
|
|
64
|
+
Note that if the name error persists even after using run_all_cells, it means that the variable is not defined in the notebook and you should not reuse this tool. Additionally, this tool could also be used to refresh the notebook state.
|
|
65
|
+
|
|
66
|
+
<Example>
|
|
67
|
+
|
|
68
|
+
<Input>
|
|
69
|
+
|
|
70
|
+
{FILES_SECTION_HEADING}
|
|
71
|
+
file_name: sales.csv
|
|
72
|
+
|
|
73
|
+
Jupyter Notebook:
|
|
74
|
+
[
|
|
75
|
+
{{
|
|
76
|
+
cell_type: 'markdown'
|
|
77
|
+
id: '9e38c62b-38f8-457d-bb8d-28bfc52edf2c'
|
|
78
|
+
code: \"\"\"# Transaction Analysis \"\"\"
|
|
79
|
+
}},
|
|
80
|
+
{{
|
|
81
|
+
cell_type: 'code'
|
|
82
|
+
id: 'adslkaf-jf73-l8xn-92j7-kjd8kdcnd2kso'
|
|
83
|
+
code: \"\"\" 'df' = pd.DataFrame({{
|
|
84
|
+
'order_id': [1, 2, 3, 4],
|
|
85
|
+
'date': ['Mar 7, 2025', 'Sep 24, 2024', '25 June, 2024', 'June 29, 2024'],
|
|
86
|
+
'amount': [100, 150, 299, 99]
|
|
87
|
+
}})
|
|
88
|
+
}},
|
|
89
|
+
{{
|
|
90
|
+
cell_type: 'code'
|
|
91
|
+
id: 'c68fdf19-db8c-46dd-926f-d90ad35bb3bc'
|
|
92
|
+
code: \"\"\"df['date'] = pd.to_datetime(df['date'])\"\"\"
|
|
93
|
+
}},
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
{VARIABLES_SECTION_HEADING}
|
|
97
|
+
{{
|
|
98
|
+
'df': pd.DataFrame({{
|
|
99
|
+
'order_id': [1, 2, 3, 4],
|
|
100
|
+
'date': ['Mar 7, 2025', 'Sep 24, 2024', '25 June, 2024', 'June 29, 2024'],
|
|
101
|
+
'amount': [100, 150, 299, 99]
|
|
102
|
+
}})
|
|
103
|
+
}}
|
|
104
|
+
|
|
105
|
+
Cell ID of the Error Producing Code Cell:
|
|
106
|
+
'c68fdf19-db8c-46dd-926f-d90ad35bb3bc'
|
|
107
|
+
|
|
108
|
+
Error Traceback:
|
|
109
|
+
Cell In[27], line 1
|
|
110
|
+
----> 1 df['date'] = pd.to_datetime(df['date'])
|
|
111
|
+
|
|
112
|
+
ValueError: time data "25 June, 2024" doesn't match format "%b %d, %Y", at position 2. You might want to try:
|
|
113
|
+
- passing `format` if your strings have a consistent format;
|
|
114
|
+
- passing `format='ISO8601'` if your strings are all ISO8601 but not necessarily in exactly the same format;
|
|
115
|
+
- passing `format='mixed'`, and the format will be inferred for each element individually. You might want to use `dayfirst` alongside this.
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
</ Input>
|
|
119
|
+
|
|
120
|
+
< Your Thinking >
|
|
121
|
+
|
|
122
|
+
ERROR ANALYSIS
|
|
123
|
+
This is a ValueError caused by applying the wrong format to a specific date string. Because it was triggered at position 2, the first date string must have successfully converted. By looking at the defined variables, I can see that first date string is in the format "Mar 7, 2025", but the third date string is in the format "25 June, 2024". Those dates are not in the same format, so the conversion failed.
|
|
124
|
+
|
|
125
|
+
INTENT PRESERVATION:
|
|
126
|
+
User is trying to convert the date column to a datetime object even though the dates are not in the same starting format.
|
|
127
|
+
|
|
128
|
+
</ Your Thinking >
|
|
129
|
+
|
|
130
|
+
<Output>
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
{{
|
|
134
|
+
is_finished: false,
|
|
135
|
+
cell_update: {{
|
|
136
|
+
type: 'modification'
|
|
137
|
+
id: 'c68fdf19-db8c-46dd-926f-d90ad35bb3bc'
|
|
138
|
+
code: "def parse_date(date_str):\n formats = ['%b %d, %Y', '%d %B, %Y']\n\n for fmt in formats:\n try:\n return pd.to_datetime(date_str, format=fmt)\n except ValueError:\n # Try next format\n continue\n\n # If not format worked, return Not a Time\n return pd.NaT\n\ndf['date'] = df['date'].apply(lambda x: parse_date(x))"
|
|
139
|
+
}}
|
|
140
|
+
}}
|
|
141
|
+
|
|
142
|
+
</Output>
|
|
143
|
+
|
|
144
|
+
</Example>
|
|
145
|
+
|
|
146
|
+
{FILES_SECTION_HEADING}
|
|
147
|
+
{files_str}
|
|
148
|
+
|
|
149
|
+
{JUPYTER_NOTEBOOK_SECTION_HEADING}
|
|
150
|
+
{ai_optimized_cells_str}
|
|
151
|
+
|
|
152
|
+
{VARIABLES_SECTION_HEADING}
|
|
153
|
+
{variables_str}
|
|
154
|
+
|
|
155
|
+
Cell ID of the Error Producing Code Cell:
|
|
156
|
+
{md.error_message_producing_code_cell_id}
|
|
157
|
+
|
|
158
|
+
Error Traceback:
|
|
159
|
+
{md.errorMessage}
|
|
160
|
+
"""
|