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.
Files changed (205) hide show
  1. mito_ai/__init__.py +114 -0
  2. mito_ai/_version.py +4 -0
  3. mito_ai/anthropic_client.py +334 -0
  4. mito_ai/app_deploy/__init__.py +6 -0
  5. mito_ai/app_deploy/app_deploy_utils.py +44 -0
  6. mito_ai/app_deploy/handlers.py +345 -0
  7. mito_ai/app_deploy/models.py +98 -0
  8. mito_ai/app_manager/__init__.py +4 -0
  9. mito_ai/app_manager/handlers.py +167 -0
  10. mito_ai/app_manager/models.py +71 -0
  11. mito_ai/app_manager/utils.py +24 -0
  12. mito_ai/auth/README.md +18 -0
  13. mito_ai/auth/__init__.py +6 -0
  14. mito_ai/auth/handlers.py +96 -0
  15. mito_ai/auth/urls.py +13 -0
  16. mito_ai/chat_history/handlers.py +63 -0
  17. mito_ai/chat_history/urls.py +32 -0
  18. mito_ai/completions/completion_handlers/__init__.py +3 -0
  19. mito_ai/completions/completion_handlers/agent_auto_error_fixup_handler.py +59 -0
  20. mito_ai/completions/completion_handlers/agent_execution_handler.py +66 -0
  21. mito_ai/completions/completion_handlers/chat_completion_handler.py +141 -0
  22. mito_ai/completions/completion_handlers/code_explain_handler.py +113 -0
  23. mito_ai/completions/completion_handlers/completion_handler.py +42 -0
  24. mito_ai/completions/completion_handlers/inline_completer_handler.py +48 -0
  25. mito_ai/completions/completion_handlers/smart_debug_handler.py +160 -0
  26. mito_ai/completions/completion_handlers/utils.py +147 -0
  27. mito_ai/completions/handlers.py +415 -0
  28. mito_ai/completions/message_history.py +401 -0
  29. mito_ai/completions/models.py +404 -0
  30. mito_ai/completions/prompt_builders/__init__.py +3 -0
  31. mito_ai/completions/prompt_builders/agent_execution_prompt.py +57 -0
  32. mito_ai/completions/prompt_builders/agent_smart_debug_prompt.py +160 -0
  33. mito_ai/completions/prompt_builders/agent_system_message.py +472 -0
  34. mito_ai/completions/prompt_builders/chat_name_prompt.py +15 -0
  35. mito_ai/completions/prompt_builders/chat_prompt.py +116 -0
  36. mito_ai/completions/prompt_builders/chat_system_message.py +92 -0
  37. mito_ai/completions/prompt_builders/explain_code_prompt.py +32 -0
  38. mito_ai/completions/prompt_builders/inline_completer_prompt.py +197 -0
  39. mito_ai/completions/prompt_builders/prompt_constants.py +170 -0
  40. mito_ai/completions/prompt_builders/smart_debug_prompt.py +199 -0
  41. mito_ai/completions/prompt_builders/utils.py +84 -0
  42. mito_ai/completions/providers.py +284 -0
  43. mito_ai/constants.py +63 -0
  44. mito_ai/db/__init__.py +3 -0
  45. mito_ai/db/crawlers/__init__.py +6 -0
  46. mito_ai/db/crawlers/base_crawler.py +61 -0
  47. mito_ai/db/crawlers/constants.py +43 -0
  48. mito_ai/db/crawlers/snowflake.py +71 -0
  49. mito_ai/db/handlers.py +168 -0
  50. mito_ai/db/models.py +31 -0
  51. mito_ai/db/urls.py +34 -0
  52. mito_ai/db/utils.py +185 -0
  53. mito_ai/docker/mssql/compose.yml +37 -0
  54. mito_ai/docker/mssql/init/setup.sql +21 -0
  55. mito_ai/docker/mysql/compose.yml +18 -0
  56. mito_ai/docker/mysql/init/setup.sql +13 -0
  57. mito_ai/docker/oracle/compose.yml +17 -0
  58. mito_ai/docker/oracle/init/setup.sql +20 -0
  59. mito_ai/docker/postgres/compose.yml +17 -0
  60. mito_ai/docker/postgres/init/setup.sql +13 -0
  61. mito_ai/enterprise/__init__.py +3 -0
  62. mito_ai/enterprise/utils.py +15 -0
  63. mito_ai/file_uploads/__init__.py +3 -0
  64. mito_ai/file_uploads/handlers.py +248 -0
  65. mito_ai/file_uploads/urls.py +21 -0
  66. mito_ai/gemini_client.py +232 -0
  67. mito_ai/log/handlers.py +38 -0
  68. mito_ai/log/urls.py +21 -0
  69. mito_ai/logger.py +37 -0
  70. mito_ai/openai_client.py +382 -0
  71. mito_ai/path_utils.py +70 -0
  72. mito_ai/rules/handlers.py +44 -0
  73. mito_ai/rules/urls.py +22 -0
  74. mito_ai/rules/utils.py +56 -0
  75. mito_ai/settings/handlers.py +41 -0
  76. mito_ai/settings/urls.py +20 -0
  77. mito_ai/settings/utils.py +42 -0
  78. mito_ai/streamlit_conversion/agent_utils.py +37 -0
  79. mito_ai/streamlit_conversion/prompts/prompt_constants.py +172 -0
  80. mito_ai/streamlit_conversion/prompts/prompt_utils.py +10 -0
  81. mito_ai/streamlit_conversion/prompts/streamlit_app_creation_prompt.py +46 -0
  82. mito_ai/streamlit_conversion/prompts/streamlit_error_correction_prompt.py +28 -0
  83. mito_ai/streamlit_conversion/prompts/streamlit_finish_todo_prompt.py +45 -0
  84. mito_ai/streamlit_conversion/prompts/streamlit_system_prompt.py +56 -0
  85. mito_ai/streamlit_conversion/prompts/update_existing_app_prompt.py +50 -0
  86. mito_ai/streamlit_conversion/search_replace_utils.py +94 -0
  87. mito_ai/streamlit_conversion/streamlit_agent_handler.py +144 -0
  88. mito_ai/streamlit_conversion/streamlit_utils.py +85 -0
  89. mito_ai/streamlit_conversion/validate_streamlit_app.py +105 -0
  90. mito_ai/streamlit_preview/__init__.py +6 -0
  91. mito_ai/streamlit_preview/handlers.py +111 -0
  92. mito_ai/streamlit_preview/manager.py +152 -0
  93. mito_ai/streamlit_preview/urls.py +22 -0
  94. mito_ai/streamlit_preview/utils.py +29 -0
  95. mito_ai/tests/__init__.py +3 -0
  96. mito_ai/tests/chat_history/test_chat_history.py +211 -0
  97. mito_ai/tests/completions/completion_handlers_utils_test.py +190 -0
  98. mito_ai/tests/conftest.py +53 -0
  99. mito_ai/tests/create_agent_system_message_prompt_test.py +22 -0
  100. mito_ai/tests/data/prompt_lg.py +69 -0
  101. mito_ai/tests/data/prompt_sm.py +6 -0
  102. mito_ai/tests/data/prompt_xl.py +13 -0
  103. mito_ai/tests/data/stock_data.sqlite3 +0 -0
  104. mito_ai/tests/db/conftest.py +39 -0
  105. mito_ai/tests/db/connections_test.py +102 -0
  106. mito_ai/tests/db/mssql_test.py +29 -0
  107. mito_ai/tests/db/mysql_test.py +29 -0
  108. mito_ai/tests/db/oracle_test.py +29 -0
  109. mito_ai/tests/db/postgres_test.py +29 -0
  110. mito_ai/tests/db/schema_test.py +93 -0
  111. mito_ai/tests/db/sqlite_test.py +31 -0
  112. mito_ai/tests/db/test_db_constants.py +61 -0
  113. mito_ai/tests/deploy_app/test_app_deploy_utils.py +89 -0
  114. mito_ai/tests/file_uploads/__init__.py +2 -0
  115. mito_ai/tests/file_uploads/test_handlers.py +282 -0
  116. mito_ai/tests/message_history/test_generate_short_chat_name.py +120 -0
  117. mito_ai/tests/message_history/test_message_history_utils.py +469 -0
  118. mito_ai/tests/open_ai_utils_test.py +152 -0
  119. mito_ai/tests/performance_test.py +329 -0
  120. mito_ai/tests/providers/test_anthropic_client.py +447 -0
  121. mito_ai/tests/providers/test_azure.py +631 -0
  122. mito_ai/tests/providers/test_capabilities.py +120 -0
  123. mito_ai/tests/providers/test_gemini_client.py +195 -0
  124. mito_ai/tests/providers/test_mito_server_utils.py +448 -0
  125. mito_ai/tests/providers/test_model_resolution.py +130 -0
  126. mito_ai/tests/providers/test_openai_client.py +57 -0
  127. mito_ai/tests/providers/test_provider_completion_exception.py +66 -0
  128. mito_ai/tests/providers/test_provider_limits.py +42 -0
  129. mito_ai/tests/providers/test_providers.py +382 -0
  130. mito_ai/tests/providers/test_retry_logic.py +389 -0
  131. mito_ai/tests/providers/test_stream_mito_server_utils.py +140 -0
  132. mito_ai/tests/providers/utils.py +85 -0
  133. mito_ai/tests/rules/conftest.py +26 -0
  134. mito_ai/tests/rules/rules_test.py +117 -0
  135. mito_ai/tests/server_limits_test.py +406 -0
  136. mito_ai/tests/settings/conftest.py +26 -0
  137. mito_ai/tests/settings/settings_test.py +70 -0
  138. mito_ai/tests/settings/test_settings_constants.py +9 -0
  139. mito_ai/tests/streamlit_conversion/__init__.py +3 -0
  140. mito_ai/tests/streamlit_conversion/test_apply_search_replace.py +240 -0
  141. mito_ai/tests/streamlit_conversion/test_streamlit_agent_handler.py +246 -0
  142. mito_ai/tests/streamlit_conversion/test_streamlit_utils.py +193 -0
  143. mito_ai/tests/streamlit_conversion/test_validate_streamlit_app.py +112 -0
  144. mito_ai/tests/streamlit_preview/test_streamlit_preview_handler.py +118 -0
  145. mito_ai/tests/streamlit_preview/test_streamlit_preview_manager.py +292 -0
  146. mito_ai/tests/test_constants.py +47 -0
  147. mito_ai/tests/test_telemetry.py +12 -0
  148. mito_ai/tests/user/__init__.py +2 -0
  149. mito_ai/tests/user/test_user.py +120 -0
  150. mito_ai/tests/utils/__init__.py +3 -0
  151. mito_ai/tests/utils/test_anthropic_utils.py +162 -0
  152. mito_ai/tests/utils/test_gemini_utils.py +98 -0
  153. mito_ai/tests/version_check_test.py +169 -0
  154. mito_ai/user/handlers.py +45 -0
  155. mito_ai/user/urls.py +21 -0
  156. mito_ai/utils/__init__.py +3 -0
  157. mito_ai/utils/anthropic_utils.py +168 -0
  158. mito_ai/utils/create.py +94 -0
  159. mito_ai/utils/db.py +74 -0
  160. mito_ai/utils/error_classes.py +42 -0
  161. mito_ai/utils/gemini_utils.py +133 -0
  162. mito_ai/utils/message_history_utils.py +87 -0
  163. mito_ai/utils/mito_server_utils.py +242 -0
  164. mito_ai/utils/open_ai_utils.py +200 -0
  165. mito_ai/utils/provider_utils.py +49 -0
  166. mito_ai/utils/schema.py +86 -0
  167. mito_ai/utils/server_limits.py +152 -0
  168. mito_ai/utils/telemetry_utils.py +480 -0
  169. mito_ai/utils/utils.py +89 -0
  170. mito_ai/utils/version_utils.py +94 -0
  171. mito_ai/utils/websocket_base.py +88 -0
  172. mito_ai/version_check.py +60 -0
  173. mito_ai-0.1.50.data/data/etc/jupyter/jupyter_server_config.d/mito_ai.json +7 -0
  174. mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/build_log.json +728 -0
  175. mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/package.json +243 -0
  176. mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/schemas/mito_ai/package.json.orig +238 -0
  177. mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/schemas/mito_ai/toolbar-buttons.json +37 -0
  178. mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/static/lib_index_js.8f1845da6bf2b128c049.js +21602 -0
  179. mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/static/lib_index_js.8f1845da6bf2b128c049.js.map +1 -0
  180. mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/static/node_modules_process_browser_js.4b128e94d31a81ebd209.js +198 -0
  181. mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/static/node_modules_process_browser_js.4b128e94d31a81ebd209.js.map +1 -0
  182. mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/static/remoteEntry.78d3ccb73e7ca1da3aae.js +619 -0
  183. mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/static/remoteEntry.78d3ccb73e7ca1da3aae.js.map +1 -0
  184. mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/static/style.js +4 -0
  185. mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/static/style_index_js.5876024bb17dbd6a3ee6.js +712 -0
  186. mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/static/style_index_js.5876024bb17dbd6a3ee6.js.map +1 -0
  187. 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
  188. 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
  189. 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
  190. 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
  191. 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
  192. 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
  193. 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
  194. 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
  195. 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
  196. 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
  197. mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_semver_index_js.3f6754ac5116d47de76b.js +2792 -0
  198. mito_ai-0.1.50.data/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_semver_index_js.3f6754ac5116d47de76b.js.map +1 -0
  199. 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
  200. 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
  201. mito_ai-0.1.50.dist-info/METADATA +221 -0
  202. mito_ai-0.1.50.dist-info/RECORD +205 -0
  203. mito_ai-0.1.50.dist-info/WHEEL +4 -0
  204. mito_ai-0.1.50.dist-info/entry_points.txt +2 -0
  205. 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,3 @@
1
+ # Copyright (c) Saga Inc.
2
+ # Distributed under the terms of the GNU Affero General Public License v3.0 License.
3
+
@@ -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
+ """