mito-ai 0.1.47__py3-none-any.whl → 0.1.48__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.

Potentially problematic release.


This version of mito-ai might be problematic. Click here for more details.

Files changed (55) hide show
  1. mito_ai/_version.py +1 -1
  2. mito_ai/app_deploy/handlers.py +3 -2
  3. mito_ai/completions/models.py +1 -0
  4. mito_ai/completions/prompt_builders/agent_execution_prompt.py +4 -0
  5. mito_ai/completions/prompt_builders/agent_system_message.py +1 -1
  6. mito_ai/path_utils.py +1 -1
  7. mito_ai/streamlit_conversion/search_replace_utils.py +4 -3
  8. mito_ai/streamlit_conversion/streamlit_agent_handler.py +6 -7
  9. mito_ai/streamlit_conversion/streamlit_utils.py +1 -2
  10. mito_ai/streamlit_conversion/validate_streamlit_app.py +2 -4
  11. mito_ai/streamlit_preview/__init__.py +1 -2
  12. mito_ai/streamlit_preview/handlers.py +17 -9
  13. mito_ai/streamlit_preview/manager.py +2 -11
  14. mito_ai/streamlit_preview/utils.py +1 -18
  15. mito_ai/tests/message_history/test_message_history_utils.py +1 -0
  16. mito_ai/tests/streamlit_conversion/test_apply_search_replace.py +18 -4
  17. mito_ai/tests/streamlit_conversion/test_streamlit_agent_handler.py +12 -9
  18. mito_ai/tests/streamlit_conversion/test_validate_streamlit_app.py +20 -18
  19. mito_ai/tests/streamlit_preview/test_streamlit_preview_handler.py +80 -52
  20. mito_ai/tests/streamlit_preview/test_streamlit_preview_manager.py +2 -11
  21. mito_ai/utils/telemetry_utils.py +9 -9
  22. {mito_ai-0.1.47.data → mito_ai-0.1.48.data}/data/share/jupyter/labextensions/mito_ai/build_log.json +100 -100
  23. {mito_ai-0.1.47.data → mito_ai-0.1.48.data}/data/share/jupyter/labextensions/mito_ai/package.json +2 -2
  24. {mito_ai-0.1.47.data → mito_ai-0.1.48.data}/data/share/jupyter/labextensions/mito_ai/schemas/mito_ai/package.json.orig +1 -1
  25. mito_ai-0.1.47.data/data/share/jupyter/labextensions/mito_ai/static/lib_index_js.2db61d2b629817845901.js → mito_ai-0.1.48.data/data/share/jupyter/labextensions/mito_ai/static/lib_index_js.5c7d84a45ddeb5704b61.js +239 -154
  26. mito_ai-0.1.48.data/data/share/jupyter/labextensions/mito_ai/static/lib_index_js.5c7d84a45ddeb5704b61.js.map +1 -0
  27. mito_ai-0.1.47.data/data/share/jupyter/labextensions/mito_ai/static/remoteEntry.e22c6cd4e56c32116daa.js → mito_ai-0.1.48.data/data/share/jupyter/labextensions/mito_ai/static/remoteEntry.045d65d1de6fde3f3b72.js +16 -16
  28. mito_ai-0.1.47.data/data/share/jupyter/labextensions/mito_ai/static/remoteEntry.e22c6cd4e56c32116daa.js.map → mito_ai-0.1.48.data/data/share/jupyter/labextensions/mito_ai/static/remoteEntry.045d65d1de6fde3f3b72.js.map +1 -1
  29. {mito_ai-0.1.47.dist-info → mito_ai-0.1.48.dist-info}/METADATA +1 -1
  30. {mito_ai-0.1.47.dist-info → mito_ai-0.1.48.dist-info}/RECORD +54 -54
  31. mito_ai-0.1.47.data/data/share/jupyter/labextensions/mito_ai/static/lib_index_js.2db61d2b629817845901.js.map +0 -1
  32. {mito_ai-0.1.47.data → mito_ai-0.1.48.data}/data/etc/jupyter/jupyter_server_config.d/mito_ai.json +0 -0
  33. {mito_ai-0.1.47.data → mito_ai-0.1.48.data}/data/share/jupyter/labextensions/mito_ai/schemas/mito_ai/toolbar-buttons.json +0 -0
  34. {mito_ai-0.1.47.data → mito_ai-0.1.48.data}/data/share/jupyter/labextensions/mito_ai/static/node_modules_process_browser_js.4b128e94d31a81ebd209.js +0 -0
  35. {mito_ai-0.1.47.data → mito_ai-0.1.48.data}/data/share/jupyter/labextensions/mito_ai/static/node_modules_process_browser_js.4b128e94d31a81ebd209.js.map +0 -0
  36. {mito_ai-0.1.47.data → mito_ai-0.1.48.data}/data/share/jupyter/labextensions/mito_ai/static/style.js +0 -0
  37. {mito_ai-0.1.47.data → mito_ai-0.1.48.data}/data/share/jupyter/labextensions/mito_ai/static/style_index_js.5876024bb17dbd6a3ee6.js +0 -0
  38. {mito_ai-0.1.47.data → mito_ai-0.1.48.data}/data/share/jupyter/labextensions/mito_ai/static/style_index_js.5876024bb17dbd6a3ee6.js.map +0 -0
  39. {mito_ai-0.1.47.data → mito_ai-0.1.48.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_auth_dist_esm_providers_cognito_apis_signOut_mjs-node_module-75790d.688c25857e7b81b1740f.js +0 -0
  40. {mito_ai-0.1.47.data → mito_ai-0.1.48.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_auth_dist_esm_providers_cognito_apis_signOut_mjs-node_module-75790d.688c25857e7b81b1740f.js.map +0 -0
  41. {mito_ai-0.1.47.data → mito_ai-0.1.48.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_auth_dist_esm_providers_cognito_tokenProvider_tokenProvider_-72f1c8.a917210f057fcfe224ad.js +0 -0
  42. {mito_ai-0.1.47.data → mito_ai-0.1.48.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_auth_dist_esm_providers_cognito_tokenProvider_tokenProvider_-72f1c8.a917210f057fcfe224ad.js.map +0 -0
  43. {mito_ai-0.1.47.data → mito_ai-0.1.48.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_dist_esm_index_mjs.6bac1a8c4cc93f15f6b7.js +0 -0
  44. {mito_ai-0.1.47.data → mito_ai-0.1.48.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_dist_esm_index_mjs.6bac1a8c4cc93f15f6b7.js.map +0 -0
  45. {mito_ai-0.1.47.data → mito_ai-0.1.48.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_ui-react_dist_esm_index_mjs.4fcecd65bef9e9847609.js +0 -0
  46. {mito_ai-0.1.47.data → mito_ai-0.1.48.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_ui-react_dist_esm_index_mjs.4fcecd65bef9e9847609.js.map +0 -0
  47. {mito_ai-0.1.47.data → mito_ai-0.1.48.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_react-dom_client_js-node_modules_aws-amplify_ui-react_dist_styles_css.b43d4249e4d3dac9ad7b.js +0 -0
  48. {mito_ai-0.1.47.data → mito_ai-0.1.48.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_react-dom_client_js-node_modules_aws-amplify_ui-react_dist_styles_css.b43d4249e4d3dac9ad7b.js.map +0 -0
  49. {mito_ai-0.1.47.data → mito_ai-0.1.48.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_semver_index_js.3f6754ac5116d47de76b.js +0 -0
  50. {mito_ai-0.1.47.data → mito_ai-0.1.48.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_semver_index_js.3f6754ac5116d47de76b.js.map +0 -0
  51. {mito_ai-0.1.47.data → mito_ai-0.1.48.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_vscode-diff_dist_index_js.ea55f1f9346638aafbcf.js +0 -0
  52. {mito_ai-0.1.47.data → mito_ai-0.1.48.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_vscode-diff_dist_index_js.ea55f1f9346638aafbcf.js.map +0 -0
  53. {mito_ai-0.1.47.dist-info → mito_ai-0.1.48.dist-info}/WHEEL +0 -0
  54. {mito_ai-0.1.47.dist-info → mito_ai-0.1.48.dist-info}/entry_points.txt +0 -0
  55. {mito_ai-0.1.47.dist-info → mito_ai-0.1.48.dist-info}/licenses/LICENSE +0 -0
@@ -360,6 +360,7 @@ class ChatHistoryManager {
360
360
  const streamlitAppIsOpen = this.checkIfStreamlitAppIsOpen();
361
361
  const agentExecutionMetadata = {
362
362
  promptType: 'agent:execution',
363
+ activeCellId: (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_1__.getActiveCellIDInNotebookPanel)(notebookPanel) || '',
363
364
  variables: (notebookContext === null || notebookContext === void 0 ? void 0 : notebookContext.variables) || [],
364
365
  files: (notebookContext === null || notebookContext === void 0 ? void 0 : notebookContext.files) || [],
365
366
  aiOptimizedCells: aiOptimizedCells,
@@ -1022,15 +1023,16 @@ __webpack_require__.r(__webpack_exports__);
1022
1023
  /* harmony export */ });
1023
1024
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "webpack/sharing/consume/default/react");
1024
1025
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
1025
- /* harmony import */ var _utils_classNames__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../../utils/classNames */ "./lib/utils/classNames.js");
1026
- /* harmony import */ var _ChatDropdown__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./ChatDropdown */ "./lib/Extensions/AiChat/ChatMessage/ChatDropdown.js");
1026
+ /* harmony import */ var _utils_classNames__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../../utils/classNames */ "./lib/utils/classNames.js");
1027
+ /* harmony import */ var _ChatDropdown__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./ChatDropdown */ "./lib/Extensions/AiChat/ChatMessage/ChatDropdown.js");
1027
1028
  /* harmony import */ var _utils_notebook__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../utils/notebook */ "./lib/utils/notebook.js");
1028
1029
  /* harmony import */ var _style_ChatInput_css__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../style/ChatInput.css */ "./style/ChatInput.css");
1029
1030
  /* harmony import */ var _style_ChatDropdown_css__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../../style/ChatDropdown.css */ "./style/ChatDropdown.css");
1030
- /* harmony import */ var _hooks_useDebouncedFunction__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../../hooks/useDebouncedFunction */ "./lib/hooks/useDebouncedFunction.js");
1031
- /* harmony import */ var _components_SelectedContextContainer__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../../components/SelectedContextContainer */ "./lib/components/SelectedContextContainer.js");
1032
- /* harmony import */ var _components_AttachFileButton__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../../components/AttachFileButton */ "./lib/components/AttachFileButton.js");
1033
- /* harmony import */ var _components_DatabaseButton__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../../components/DatabaseButton */ "./lib/components/DatabaseButton.js");
1031
+ /* harmony import */ var _hooks_useDebouncedFunction__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../../hooks/useDebouncedFunction */ "./lib/hooks/useDebouncedFunction.js");
1032
+ /* harmony import */ var _components_SelectedContextContainer__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../../components/SelectedContextContainer */ "./lib/components/SelectedContextContainer.js");
1033
+ /* harmony import */ var _components_AttachFileButton__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../../components/AttachFileButton */ "./lib/components/AttachFileButton.js");
1034
+ /* harmony import */ var _components_DatabaseButton__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../../components/DatabaseButton */ "./lib/components/DatabaseButton.js");
1035
+ /* harmony import */ var _utils_fileUpload__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../../utils/fileUpload */ "./lib/utils/fileUpload.js");
1034
1036
  /*
1035
1037
  * Copyright (c) Saga Inc.
1036
1038
  * Distributed under the terms of the GNU Affero General Public License v3.0 License.
@@ -1045,6 +1047,7 @@ __webpack_require__.r(__webpack_exports__);
1045
1047
 
1046
1048
 
1047
1049
 
1050
+
1048
1051
  const ChatInput = ({ app, initialContent, onSave, onCancel, isEditing, contextManager, notebookTracker, agentModeEnabled = false, agentExecutionStatus = 'idle', operatingSystem = 'mac', displayOptimizedChatHistoryLength = 0, agentTargetNotebookPanelRef, isSignedUp = true, }) => {
1049
1052
  var _a;
1050
1053
  const [input, setInput] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(initialContent);
@@ -1055,6 +1058,8 @@ const ChatInput = ({ app, initialContent, onSave, onCancel, isEditing, contextMa
1055
1058
  const [dropdownFilter, setDropdownFilter] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)('');
1056
1059
  const [additionalContext, setAdditionalContext] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)([]);
1057
1060
  const [isDropdownFromButton, setIsDropdownFromButton] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false);
1061
+ const [isDragOver, setIsDragOver] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false);
1062
+ const [isUploading, setIsUploading] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false);
1058
1063
  const handleFileUpload = (file) => {
1059
1064
  let uploadType;
1060
1065
  if (file.type.startsWith('image/')) {
@@ -1075,9 +1080,45 @@ const ChatInput = ({ app, initialContent, onSave, onCancel, isEditing, contextMa
1075
1080
  }
1076
1081
  ]);
1077
1082
  };
1083
+ // Drag and drop handlers
1084
+ const handleDragOver = (e) => {
1085
+ e.preventDefault();
1086
+ e.stopPropagation();
1087
+ // Only show drag over state if not currently uploading
1088
+ if (!isUploading) {
1089
+ setIsDragOver(true);
1090
+ }
1091
+ };
1092
+ const handleDragLeave = (e) => {
1093
+ e.preventDefault();
1094
+ e.stopPropagation();
1095
+ setIsDragOver(false);
1096
+ };
1097
+ const handleDrop = async (e) => {
1098
+ e.preventDefault();
1099
+ e.stopPropagation();
1100
+ setIsDragOver(false);
1101
+ const files = e.dataTransfer.files;
1102
+ if (files && files.length > 0) {
1103
+ const file = files[0];
1104
+ if (file && !isUploading) {
1105
+ setIsUploading(true);
1106
+ try {
1107
+ // Upload file to backend using the shared utility
1108
+ await (0,_utils_fileUpload__WEBPACK_IMPORTED_MODULE_4__.uploadFileToBackend)(file, notebookTracker, handleFileUpload);
1109
+ }
1110
+ catch (error) {
1111
+ // Error handling is already done in the utility function
1112
+ }
1113
+ finally {
1114
+ setIsUploading(false);
1115
+ }
1116
+ }
1117
+ }
1118
+ };
1078
1119
  // Debounce the active cell ID change to avoid multiple rerenders.
1079
1120
  // We use this to avoid a flickering screen when the active cell changes.
1080
- const debouncedSetActiveCellID = (0,_hooks_useDebouncedFunction__WEBPACK_IMPORTED_MODULE_4__.useDebouncedFunction)((newID) => {
1121
+ const debouncedSetActiveCellID = (0,_hooks_useDebouncedFunction__WEBPACK_IMPORTED_MODULE_5__.useDebouncedFunction)((newID) => {
1081
1122
  setActiveCellID(newID);
1082
1123
  }, 100);
1083
1124
  (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {
@@ -1305,10 +1346,13 @@ const ChatInput = ({ app, initialContent, onSave, onCancel, isEditing, contextMa
1305
1346
  }
1306
1347
  }
1307
1348
  }, [agentModeEnabled, additionalContext, activeCellCode]);
1308
- return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: (0,_utils_classNames__WEBPACK_IMPORTED_MODULE_5__.classNames)("chat-input-container", { "editing": isEditing }) },
1349
+ return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: (0,_utils_classNames__WEBPACK_IMPORTED_MODULE_6__.classNames)("chat-input-container", {
1350
+ "editing": isEditing,
1351
+ "drag-over": isDragOver
1352
+ }), onDragOver: handleDragOver, onDragLeave: handleDragLeave, onDrop: handleDrop },
1309
1353
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: 'context-container' },
1310
- react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_DatabaseButton__WEBPACK_IMPORTED_MODULE_6__["default"], { app: app }),
1311
- react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_AttachFileButton__WEBPACK_IMPORTED_MODULE_7__["default"], { onFileUploaded: handleFileUpload, notebookTracker: notebookTracker }),
1354
+ react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_DatabaseButton__WEBPACK_IMPORTED_MODULE_7__["default"], { app: app }),
1355
+ react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_AttachFileButton__WEBPACK_IMPORTED_MODULE_8__["default"], { onFileUploaded: handleFileUpload, notebookTracker: notebookTracker }),
1312
1356
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement("button", { className: "context-button", onClick: () => {
1313
1357
  var _a;
1314
1358
  setDropdownVisible(true);
@@ -1316,9 +1360,9 @@ const ChatInput = ({ app, initialContent, onSave, onCancel, isEditing, contextMa
1316
1360
  setIsDropdownFromButton(true);
1317
1361
  (_a = textAreaRef.current) === null || _a === void 0 ? void 0 : _a.focus();
1318
1362
  } }, "\uFF20 Add Context"),
1319
- additionalContext.map((context, index) => (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_SelectedContextContainer__WEBPACK_IMPORTED_MODULE_8__["default"], { key: `${context.type}-${context.value}-${index}`, title: context.display || context.value, type: context.type, onRemove: () => setAdditionalContext(additionalContext.filter((_, i) => i !== index)), notebookTracker: notebookTracker, activeCellID: activeCellID })))),
1363
+ additionalContext.map((context, index) => (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_SelectedContextContainer__WEBPACK_IMPORTED_MODULE_9__["default"], { key: `${context.type}-${context.value}-${index}`, title: context.display || context.value, type: context.type, onRemove: () => setAdditionalContext(additionalContext.filter((_, i) => i !== index)), notebookTracker: notebookTracker, activeCellID: activeCellID })))),
1320
1364
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: 'chat-input-text-area-container' },
1321
- react__WEBPACK_IMPORTED_MODULE_0___default().createElement("textarea", { ref: textAreaRef, className: (0,_utils_classNames__WEBPACK_IMPORTED_MODULE_5__.classNames)("message", "message-user", 'chat-input', { "agent-mode": agentModeEnabled }), placeholder: getPlaceholderText(), value: input, disabled: agentExecutionStatus === 'working' || agentExecutionStatus === 'stopping', onChange: handleInputChange, onKeyDown: (e) => {
1365
+ react__WEBPACK_IMPORTED_MODULE_0___default().createElement("textarea", { ref: textAreaRef, className: (0,_utils_classNames__WEBPACK_IMPORTED_MODULE_6__.classNames)("message", "message-user", 'chat-input', { "agent-mode": agentModeEnabled }), placeholder: getPlaceholderText(), value: input, disabled: agentExecutionStatus === 'working' || agentExecutionStatus === 'stopping', onChange: handleInputChange, onKeyDown: (e) => {
1322
1366
  // If dropdown is visible, only handle escape to close it
1323
1367
  if (isDropdownVisible) {
1324
1368
  if (e.key === 'Escape') {
@@ -1345,7 +1389,7 @@ const ChatInput = ({ app, initialContent, onSave, onCancel, isEditing, contextMa
1345
1389
  }
1346
1390
  }
1347
1391
  } }),
1348
- isDropdownVisible && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_ChatDropdown__WEBPACK_IMPORTED_MODULE_9__["default"], { options: getExpandedVarialbes(), onSelect: handleOptionSelect, filterText: dropdownFilter, isDropdownFromButton: isDropdownFromButton, onFilterChange: setDropdownFilter, onClose: handleDropdownClose }))),
1392
+ isDropdownVisible && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_ChatDropdown__WEBPACK_IMPORTED_MODULE_10__["default"], { options: getExpandedVarialbes(), onSelect: handleOptionSelect, filterText: dropdownFilter, isDropdownFromButton: isDropdownFromButton, onFilterChange: setDropdownFilter, onClose: handleDropdownClose }))),
1349
1393
  isEditing &&
1350
1394
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: "message-edit-buttons" },
1351
1395
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement("button", { onClick: () => onSave(input, undefined, mapAdditionalContext()) }, "Save"),
@@ -4255,6 +4299,10 @@ const deployStreamlitApp = async (notebookPanel, appDeployService, appManagerSer
4255
4299
  }
4256
4300
  catch (error) {
4257
4301
  console.log('Authentication cancelled or failed:', error);
4302
+ const errorMsg = 'Authentication failed: ' + error;
4303
+ _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_0__.Notification.emit(errorMsg, 'error', {
4304
+ autoClose: false
4305
+ });
4258
4306
  return; // Exit early if authentication was cancelled
4259
4307
  }
4260
4308
  }
@@ -4271,6 +4319,10 @@ const deployStreamlitApp = async (notebookPanel, appDeployService, appManagerSer
4271
4319
  selectedFiles = await (0,_FilesSelectorUtils__WEBPACK_IMPORTED_MODULE_6__.fileSelectorPopup)(notebookPath);
4272
4320
  }
4273
4321
  catch (error) {
4322
+ const errorMsg = 'Files selection failed: ' + error;
4323
+ _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_0__.Notification.emit(errorMsg, 'error', {
4324
+ autoClose: false
4325
+ });
4274
4326
  console.log('File selection failed:', error);
4275
4327
  return;
4276
4328
  }
@@ -8831,11 +8883,9 @@ __webpack_require__.r(__webpack_exports__);
8831
8883
  /* harmony export */ });
8832
8884
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "webpack/sharing/consume/default/react");
8833
8885
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
8834
- /* harmony import */ var _IconButton__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./IconButton */ "./lib/components/IconButton.js");
8835
- /* harmony import */ var _icons_PaperClipIcon__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../icons/PaperClipIcon */ "./lib/icons/PaperClipIcon.js");
8836
- /* harmony import */ var _restAPI_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../restAPI/utils */ "./lib/restAPI/utils.js");
8837
- /* harmony import */ var _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @jupyterlab/apputils */ "webpack/sharing/consume/default/@jupyterlab/apputils");
8838
- /* harmony import */ var _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_1__);
8886
+ /* harmony import */ var _IconButton__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./IconButton */ "./lib/components/IconButton.js");
8887
+ /* harmony import */ var _icons_PaperClipIcon__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../icons/PaperClipIcon */ "./lib/icons/PaperClipIcon.js");
8888
+ /* harmony import */ var _utils_fileUpload__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../utils/fileUpload */ "./lib/utils/fileUpload.js");
8839
8889
  /*
8840
8890
  * Copyright (c) Saga Inc.
8841
8891
  * Distributed under the terms of the GNU Affero General Public License v3.0 License.
@@ -8844,22 +8894,9 @@ __webpack_require__.r(__webpack_exports__);
8844
8894
 
8845
8895
 
8846
8896
 
8847
-
8848
- // Constants for file handling
8849
- const CHUNKED_UPLOAD_SIZE_CUTOFF = 25 * 1024 * 1024; // 25MB cutoff for chunked uploads
8850
- const CHUNK_SIZE = 10 * 1024 * 1024; // 10MB chunks
8851
8897
  const AttachFileButton = ({ onFileUploaded, notebookTracker }) => {
8852
8898
  const fileInputRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(null);
8853
8899
  const [isUploading, setIsUploading] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false);
8854
- // Helper function to get notebook directory from notebook path
8855
- const getNotebookDirectory = (notebookPath) => {
8856
- const lastSlashIndex = notebookPath.lastIndexOf('/');
8857
- if (lastSlashIndex === -1) {
8858
- // No directory, just filename (root directory)
8859
- return '.';
8860
- }
8861
- return notebookPath.substring(0, lastSlashIndex);
8862
- };
8863
8900
  const handleClick = () => {
8864
8901
  var _a;
8865
8902
  // Don't allow clicks if uploading
@@ -8880,21 +8917,11 @@ const AttachFileButton = ({ onFileUploaded, notebookTracker }) => {
8880
8917
  return;
8881
8918
  setIsUploading(true);
8882
8919
  try {
8883
- // Check file size and handle accordingly
8884
- if (file.size > CHUNKED_UPLOAD_SIZE_CUTOFF) {
8885
- console.log(`File ${file.name} is larger than 25MB (${(file.size / (1024 * 1024)).toFixed(2)}MB). Splitting into chunks...`);
8886
- await handleLargeFile(file);
8887
- }
8888
- else {
8889
- // Upload file directly for files <= 25MB
8890
- await uploadFile(file);
8891
- }
8920
+ // Use the shared upload utility
8921
+ await (0,_utils_fileUpload__WEBPACK_IMPORTED_MODULE_1__.uploadFileToBackend)(file, notebookTracker, onFileUploaded);
8892
8922
  }
8893
8923
  catch (error) {
8894
- _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_1__.Notification.emit(`Upload failed: ${error}`, "error", {
8895
- autoClose: 5 * 1000 // 5 seconds
8896
- });
8897
- console.error('Error during file upload:', error);
8924
+ // Error handling is already done in the utility function
8898
8925
  }
8899
8926
  finally {
8900
8927
  setIsUploading(false);
@@ -8904,116 +8931,9 @@ const AttachFileButton = ({ onFileUploaded, notebookTracker }) => {
8904
8931
  }
8905
8932
  }
8906
8933
  };
8907
- const handleLargeFile = async (file) => {
8908
- const totalChunks = Math.ceil(file.size / CHUNK_SIZE);
8909
- console.log(`Splitting file into ${totalChunks} chunks of ${(CHUNK_SIZE / (1024 * 1024)).toFixed(2)}MB each`);
8910
- // Get notebook directory path
8911
- const notebookPanel = notebookTracker.currentWidget;
8912
- if (!notebookPanel) {
8913
- console.error('No notebook is currently active');
8914
- throw new Error('No notebook is currently active');
8915
- }
8916
- const notebookPath = notebookPanel.context.path;
8917
- const notebookDir = getNotebookDirectory(notebookPath);
8918
- for (let chunkIndex = 0; chunkIndex < totalChunks; chunkIndex++) {
8919
- const start = chunkIndex * CHUNK_SIZE;
8920
- const end = Math.min(start + CHUNK_SIZE, file.size);
8921
- const chunk = file.slice(start, end);
8922
- console.log(`Uploading chunk ${chunkIndex + 1}/${totalChunks}:`, {
8923
- chunkNumber: chunkIndex + 1,
8924
- totalChunks: totalChunks,
8925
- chunkSize: chunk.size,
8926
- chunkSizeMB: (chunk.size / (1024 * 1024)).toFixed(2),
8927
- startByte: start,
8928
- endByte: end,
8929
- fileName: file.name,
8930
- originalFileSize: file.size,
8931
- originalFileSizeMB: (file.size / (1024 * 1024)).toFixed(2)
8932
- });
8933
- // Upload chunk to backend
8934
- const success = await uploadChunk(chunk, file.name, chunkIndex + 1, totalChunks, notebookDir);
8935
- if (!success) {
8936
- console.error(`Failed to upload chunk ${chunkIndex + 1}`);
8937
- throw new Error(`Failed to upload chunk ${chunkIndex + 1}`);
8938
- }
8939
- }
8940
- console.log(`Successfully uploaded all ${totalChunks} chunks for file: ${file.name}`);
8941
- // Notify the parent component that the file was uploaded
8942
- onFileUploaded(file);
8943
- };
8944
- const uploadChunk = async (chunk, filename, chunkNumber, totalChunks, notebookDir) => {
8945
- try {
8946
- // Create FormData for chunk upload
8947
- const formData = new FormData();
8948
- formData.append('file', chunk, filename);
8949
- formData.append('chunk_number', chunkNumber.toString());
8950
- formData.append('total_chunks', totalChunks.toString());
8951
- formData.append('notebook_dir', notebookDir);
8952
- // Upload chunk to backend
8953
- const resp = await (0,_restAPI_utils__WEBPACK_IMPORTED_MODULE_2__.requestAPI)('upload', {
8954
- method: 'POST',
8955
- body: formData
8956
- });
8957
- if (resp.error) {
8958
- _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_1__.Notification.emit(`Upload failed: ${resp.error.message}`, "error", {
8959
- autoClose: 5 * 1000 // 5 seconds
8960
- });
8961
- console.error(`Chunk ${chunkNumber} upload failed:`, resp.error.message);
8962
- return false;
8963
- }
8964
- else if (resp.data) {
8965
- if (resp.data.chunk_complete) {
8966
- console.log(`All chunks uploaded successfully. File reconstructed: ${resp.data.filename}`);
8967
- }
8968
- else if (resp.data.chunk_received) {
8969
- console.log(`Chunk ${resp.data.chunk_number}/${resp.data.total_chunks} uploaded successfully`);
8970
- }
8971
- return true;
8972
- }
8973
- return false;
8974
- }
8975
- catch (error) {
8976
- _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_1__.Notification.emit(`Upload failed: ${error}`, "error", {
8977
- autoClose: 5 * 1000 // 5 seconds
8978
- });
8979
- console.error(`Error uploading chunk ${chunkNumber}:`, error);
8980
- return false;
8981
- }
8982
- };
8983
- const uploadFile = async (file) => {
8984
- // Get notebook directory path
8985
- const notebookPanel = notebookTracker.currentWidget;
8986
- if (!notebookPanel) {
8987
- console.error('No notebook is currently active');
8988
- throw new Error('No notebook is currently active');
8989
- }
8990
- const notebookPath = notebookPanel.context.path;
8991
- const notebookDir = getNotebookDirectory(notebookPath);
8992
- // Create FormData for file upload
8993
- const formData = new FormData();
8994
- formData.append('file', file);
8995
- formData.append('notebook_dir', notebookDir);
8996
- // Upload file to backend using FormData
8997
- const resp = await (0,_restAPI_utils__WEBPACK_IMPORTED_MODULE_2__.requestAPI)('upload', {
8998
- method: 'POST',
8999
- body: formData
9000
- });
9001
- if (resp.error) {
9002
- _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_1__.Notification.emit(`Upload failed: ${resp.error.message}`, "error", {
9003
- autoClose: 5 * 1000 // 5 seconds
9004
- });
9005
- console.error('Upload failed:', resp.error.message);
9006
- }
9007
- else if (resp.data) {
9008
- console.log('File uploaded successfully:', resp.data);
9009
- // Notify the parent component that the file was uploaded,
9010
- // which will update the context manager.
9011
- onFileUploaded(file);
9012
- }
9013
- };
9014
8934
  return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { style: { position: 'relative' } },
9015
8935
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement("input", { ref: fileInputRef, type: "file", style: { display: 'none' }, onChange: handleFileSelect, accept: "*" }),
9016
- react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_IconButton__WEBPACK_IMPORTED_MODULE_3__["default"], { icon: react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_icons_PaperClipIcon__WEBPACK_IMPORTED_MODULE_4__["default"], null), title: isUploading ? 'Uploading...' : 'Attach File', onClick: handleClick, className: 'icon-button-hover', disabled: isUploading, style: {
8936
+ react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_IconButton__WEBPACK_IMPORTED_MODULE_2__["default"], { icon: react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_icons_PaperClipIcon__WEBPACK_IMPORTED_MODULE_3__["default"], null), title: isUploading ? 'Uploading...' : 'Attach File', onClick: handleClick, className: 'icon-button-hover', disabled: isUploading, style: {
9017
8937
  ...(isUploading && { opacity: 0.5 }),
9018
8938
  cursor: isUploading ? 'not-allowed' : 'pointer'
9019
8939
  } })));
@@ -11525,6 +11445,166 @@ const stripFileEnding = (rule) => {
11525
11445
  };
11526
11446
 
11527
11447
 
11448
+ /***/ }),
11449
+
11450
+ /***/ "./lib/utils/fileUpload.js":
11451
+ /*!*********************************!*\
11452
+ !*** ./lib/utils/fileUpload.js ***!
11453
+ \*********************************/
11454
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
11455
+
11456
+ __webpack_require__.r(__webpack_exports__);
11457
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
11458
+ /* harmony export */ uploadFileToBackend: () => (/* binding */ uploadFileToBackend)
11459
+ /* harmony export */ });
11460
+ /* harmony import */ var _restAPI_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../restAPI/utils */ "./lib/restAPI/utils.js");
11461
+ /* harmony import */ var _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @jupyterlab/apputils */ "webpack/sharing/consume/default/@jupyterlab/apputils");
11462
+ /* harmony import */ var _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_0__);
11463
+ /*
11464
+ * Copyright (c) Saga Inc.
11465
+ * Distributed under the terms of the GNU Affero General Public License v3.0 License.
11466
+ */
11467
+
11468
+
11469
+ const CHUNKED_UPLOAD_SIZE_CUTOFF = 25 * 1024 * 1024; // 25MB cutoff for chunked uploads
11470
+ const CHUNK_SIZE = 10 * 1024 * 1024; // 10MB chunks
11471
+ const getNotebookDirectory = (notebookPath) => {
11472
+ const lastSlashIndex = notebookPath.lastIndexOf('/');
11473
+ if (lastSlashIndex === -1) {
11474
+ // No directory, just filename (root directory)
11475
+ return '.';
11476
+ }
11477
+ return notebookPath.substring(0, lastSlashIndex);
11478
+ };
11479
+ const uploadChunk = async (chunk, filename, chunkNumber, totalChunks, notebookDir) => {
11480
+ try {
11481
+ // Create FormData for chunk upload
11482
+ const formData = new FormData();
11483
+ formData.append('file', chunk, filename);
11484
+ formData.append('chunk_number', chunkNumber.toString());
11485
+ formData.append('total_chunks', totalChunks.toString());
11486
+ formData.append('notebook_dir', notebookDir);
11487
+ // Upload chunk to backend
11488
+ const resp = await (0,_restAPI_utils__WEBPACK_IMPORTED_MODULE_1__.requestAPI)('upload', {
11489
+ method: 'POST',
11490
+ body: formData
11491
+ });
11492
+ if (resp.error) {
11493
+ _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_0__.Notification.emit(`Upload failed: ${resp.error.message}`, "error", {
11494
+ autoClose: 5 * 1000 // 5 seconds
11495
+ });
11496
+ console.error(`Chunk ${chunkNumber} upload failed:`, resp.error.message);
11497
+ return false;
11498
+ }
11499
+ else if (resp.data) {
11500
+ if (resp.data.chunk_complete) {
11501
+ console.log(`All chunks uploaded successfully. File reconstructed: ${resp.data.filename}`);
11502
+ }
11503
+ else if (resp.data.chunk_received) {
11504
+ console.log(`Chunk ${resp.data.chunk_number}/${resp.data.total_chunks} uploaded successfully`);
11505
+ }
11506
+ return true;
11507
+ }
11508
+ return false;
11509
+ }
11510
+ catch (error) {
11511
+ _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_0__.Notification.emit(`Upload failed: ${error}`, "error", {
11512
+ autoClose: 5 * 1000 // 5 seconds
11513
+ });
11514
+ console.error(`Error uploading chunk ${chunkNumber}:`, error);
11515
+ return false;
11516
+ }
11517
+ };
11518
+ const handleLargeFile = async (file, notebookTracker, onFileUploaded) => {
11519
+ const totalChunks = Math.ceil(file.size / CHUNK_SIZE);
11520
+ console.log(`Splitting file into ${totalChunks} chunks of ${(CHUNK_SIZE / (1024 * 1024)).toFixed(2)}MB each`);
11521
+ // Get notebook directory path
11522
+ const notebookPanel = notebookTracker.currentWidget;
11523
+ if (!notebookPanel) {
11524
+ console.error('No notebook is currently active');
11525
+ throw new Error('No notebook is currently active');
11526
+ }
11527
+ const notebookPath = notebookPanel.context.path;
11528
+ const notebookDir = getNotebookDirectory(notebookPath);
11529
+ for (let chunkIndex = 0; chunkIndex < totalChunks; chunkIndex++) {
11530
+ const start = chunkIndex * CHUNK_SIZE;
11531
+ const end = Math.min(start + CHUNK_SIZE, file.size);
11532
+ const chunk = file.slice(start, end);
11533
+ console.log(`Uploading chunk ${chunkIndex + 1}/${totalChunks}:`, {
11534
+ chunkNumber: chunkIndex + 1,
11535
+ totalChunks: totalChunks,
11536
+ chunkSize: chunk.size,
11537
+ chunkSizeMB: (chunk.size / (1024 * 1024)).toFixed(2),
11538
+ startByte: start,
11539
+ endByte: end,
11540
+ fileName: file.name,
11541
+ originalFileSize: file.size,
11542
+ originalFileSizeMB: (file.size / (1024 * 1024)).toFixed(2)
11543
+ });
11544
+ // Upload chunk to backend
11545
+ const success = await uploadChunk(chunk, file.name, chunkIndex + 1, totalChunks, notebookDir);
11546
+ if (!success) {
11547
+ console.error(`Failed to upload chunk ${chunkIndex + 1}`);
11548
+ throw new Error(`Failed to upload chunk ${chunkIndex + 1}`);
11549
+ }
11550
+ }
11551
+ console.log(`Successfully uploaded all ${totalChunks} chunks for file: ${file.name}`);
11552
+ // Notify the parent component that the file was uploaded
11553
+ onFileUploaded(file);
11554
+ };
11555
+ const uploadFile = async (file, notebookTracker, onFileUploaded) => {
11556
+ // Get notebook directory path
11557
+ const notebookPanel = notebookTracker.currentWidget;
11558
+ if (!notebookPanel) {
11559
+ console.error('No notebook is currently active');
11560
+ throw new Error('No notebook is currently active');
11561
+ }
11562
+ const notebookPath = notebookPanel.context.path;
11563
+ const notebookDir = getNotebookDirectory(notebookPath);
11564
+ // Create FormData for file upload
11565
+ const formData = new FormData();
11566
+ formData.append('file', file);
11567
+ formData.append('notebook_dir', notebookDir);
11568
+ // Upload file to backend using FormData
11569
+ const resp = await (0,_restAPI_utils__WEBPACK_IMPORTED_MODULE_1__.requestAPI)('upload', {
11570
+ method: 'POST',
11571
+ body: formData
11572
+ });
11573
+ if (resp.error) {
11574
+ _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_0__.Notification.emit(`Upload failed: ${resp.error.message}`, "error", {
11575
+ autoClose: 5 * 1000 // 5 seconds
11576
+ });
11577
+ console.error('Upload failed:', resp.error.message);
11578
+ }
11579
+ else if (resp.data) {
11580
+ console.log('File uploaded successfully:', resp.data);
11581
+ // Notify the parent component that the file was uploaded,
11582
+ // which will update the context manager.
11583
+ onFileUploaded(file);
11584
+ }
11585
+ };
11586
+ const uploadFileToBackend = async (file, notebookTracker, onFileUploaded) => {
11587
+ try {
11588
+ // Check file size and handle accordingly
11589
+ if (file.size > CHUNKED_UPLOAD_SIZE_CUTOFF) {
11590
+ console.log(`File ${file.name} is larger than 25MB (${(file.size / (1024 * 1024)).toFixed(2)}MB). Splitting into chunks...`);
11591
+ await handleLargeFile(file, notebookTracker, onFileUploaded);
11592
+ }
11593
+ else {
11594
+ // Upload file directly for files <= 25MB
11595
+ await uploadFile(file, notebookTracker, onFileUploaded);
11596
+ }
11597
+ }
11598
+ catch (error) {
11599
+ _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_0__.Notification.emit(`Upload failed: ${error}`, "error", {
11600
+ autoClose: 5 * 1000 // 5 seconds
11601
+ });
11602
+ console.error('Error during file upload:', error);
11603
+ throw error;
11604
+ }
11605
+ };
11606
+
11607
+
11528
11608
  /***/ }),
11529
11609
 
11530
11610
  /***/ "./lib/utils/models.js":
@@ -14517,6 +14597,11 @@ ___CSS_LOADER_EXPORT___.push([module.id, `/*
14517
14597
  margin-top: 0;
14518
14598
  }
14519
14599
 
14600
+ .chat-input-container.drag-over {
14601
+ border: 2px dashed var(--purple-500);
14602
+ transform: scale(1.02);
14603
+ }
14604
+
14520
14605
  .chat-input-text-area-container {
14521
14606
  position: relative;
14522
14607
  height: min-content;
@@ -14597,7 +14682,7 @@ ___CSS_LOADER_EXPORT___.push([module.id, `/*
14597
14682
 
14598
14683
  .context-button:disabled:hover {
14599
14684
  background-color: var(--jp-layout-color2);
14600
- }`, "",{"version":3,"sources":["webpack://./style/ChatInput.css"],"names":[],"mappings":"AAAA;;;EAGE;;AAEF;EACE,gBAAgB;EAChB,SAAS;EACT,cAAc;EACd,gBAAgB;EAChB,2DAA2D;EAC3D;;;iCAG+B;EAC/B,WAAW;EACX,mBAAmB;EACnB,iDAAiD;AACnD;;AAEA;EACE,aAAa;AACf;;AAEA;EACE,kBAAkB;EAClB,mBAAmB;AACrB;;AAEA;EACE,aAAa;EACb,YAAY;EACZ,YAAY;EACZ,WAAW;EACX,aAAa;EACb,gBAAgB;EAChB,sBAAsB;EACtB,yBAAyB;EACzB,2DAA2D;EAC3D,eAAe;EACf,gBAAgB;EAChB,qCAAqC;EACrC,gBAAgB;EAChB,iDAAiD;AACnD;;AAEA;EACE,aAAa;AACf;;AAEA;EACE,2BAA2B;EAC3B;;;iCAG+B;AACjC;;AAEA;EACE,+BAA+B;AACjC;;AAEA;EACE,+BAA+B;EAC/B,2BAA2B;AAC7B;;AAEA;EACE,+BAA+B;AACjC;;AAEA;EACE,aAAa;EACb,mBAAmB;EACnB,yCAAyC;EACzC,yCAAyC;EACzC,kBAAkB;EAClB,gBAAgB;EAChB,eAAe;EACf,yCAAyC;EACzC,eAAe;EACf,oCAAoC;EACpC,sCAAsC;AACxC;;AAEA;EACE,yCAAyC;AAC3C;;AAEA,0BAA0B;AAC1B;EACE,YAAY;EACZ,mBAAmB;EACnB,yCAAyC;AAC3C;;AAEA;EACE,YAAY;EACZ,mBAAmB;EACnB,yCAAyC;AAC3C;;AAEA;EACE,yCAAyC;AAC3C","sourcesContent":["/*\n * Copyright (c) Saga Inc.\n * Distributed under the terms of the GNU Affero General Public License v3.0 License.\n */\n\n.chat-input-container {\n position: sticky;\n bottom: 0;\n margin: 10px 0;\n margin-top: auto;\n background-color: var(--chat-user-message-background-color);\n box-shadow: \n 0 4px 12px rgba(0, 0, 0, 0.08),\n 0 2px 4px rgba(0, 0, 0, 0.06),\n 0 0 0 1px rgba(0, 0, 0, 0.02);\n width: 100%;\n border-radius: 12px;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.chat-input-container.editing {\n margin-top: 0;\n}\n\n.chat-input-text-area-container {\n position: relative;\n height: min-content;\n}\n\n.chat-input {\n outline: none;\n border: none;\n resize: none;\n width: 100%;\n padding: 10px;\n overflow-y: auto;\n box-sizing: border-box;\n flex-shrink: 0 !important;\n background-color: var(--chat-user-message-background-color);\n font-size: 12px;\n font-weight: 400;\n font-family: var(--jp-ui-font-family);\n line-height: 1.2;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.active-cell-preview-container {\n padding: 10px;\n}\n\n.chat-input-container:focus-within {\n transform: translateY(-1px);\n box-shadow: \n 0 2px 8px rgba(0, 0, 0, 0.12),\n 0 8px 16px rgba(0, 0, 0, 0.08),\n 0 0 0 1px rgba(0, 0, 0, 0.04);\n}\n\n.chat-input:focus {\n color: var(--jp-ui-font-color1);\n}\n\n.chat-input::placeholder {\n color: var(--jp-ui-font-color2);\n transition: color 0.2s ease;\n}\n\n.chat-input:focus::placeholder {\n color: var(--jp-ui-font-color3);\n}\n\n.context-button {\n display: flex;\n align-items: center;\n background-color: var(--jp-layout-color2);\n border: 1px solid var(--jp-border-color1);\n border-radius: 3px;\n padding: 4px 8px;\n font-size: 12px;\n height: var(--chat-context-button-height);\n cursor: pointer;\n color: var(--jp-content-font-color1);\n transition: background-color 0.2s ease;\n}\n\n.context-button:hover {\n background-color: var(--jp-layout-color3);\n}\n\n/* Disabled state styles */\n.chat-input:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n background-color: var(--jp-layout-color2);\n}\n\n.context-button:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n background-color: var(--jp-layout-color2);\n}\n\n.context-button:disabled:hover {\n background-color: var(--jp-layout-color2);\n}"],"sourceRoot":""}]);
14685
+ }`, "",{"version":3,"sources":["webpack://./style/ChatInput.css"],"names":[],"mappings":"AAAA;;;EAGE;;AAEF;EACE,gBAAgB;EAChB,SAAS;EACT,cAAc;EACd,gBAAgB;EAChB,2DAA2D;EAC3D;;;iCAG+B;EAC/B,WAAW;EACX,mBAAmB;EACnB,iDAAiD;AACnD;;AAEA;EACE,aAAa;AACf;;AAEA;EACE,oCAAoC;EACpC,sBAAsB;AACxB;;AAEA;EACE,kBAAkB;EAClB,mBAAmB;AACrB;;AAEA;EACE,aAAa;EACb,YAAY;EACZ,YAAY;EACZ,WAAW;EACX,aAAa;EACb,gBAAgB;EAChB,sBAAsB;EACtB,yBAAyB;EACzB,2DAA2D;EAC3D,eAAe;EACf,gBAAgB;EAChB,qCAAqC;EACrC,gBAAgB;EAChB,iDAAiD;AACnD;;AAEA;EACE,aAAa;AACf;;AAEA;EACE,2BAA2B;EAC3B;;;iCAG+B;AACjC;;AAEA;EACE,+BAA+B;AACjC;;AAEA;EACE,+BAA+B;EAC/B,2BAA2B;AAC7B;;AAEA;EACE,+BAA+B;AACjC;;AAEA;EACE,aAAa;EACb,mBAAmB;EACnB,yCAAyC;EACzC,yCAAyC;EACzC,kBAAkB;EAClB,gBAAgB;EAChB,eAAe;EACf,yCAAyC;EACzC,eAAe;EACf,oCAAoC;EACpC,sCAAsC;AACxC;;AAEA;EACE,yCAAyC;AAC3C;;AAEA,0BAA0B;AAC1B;EACE,YAAY;EACZ,mBAAmB;EACnB,yCAAyC;AAC3C;;AAEA;EACE,YAAY;EACZ,mBAAmB;EACnB,yCAAyC;AAC3C;;AAEA;EACE,yCAAyC;AAC3C","sourcesContent":["/*\n * Copyright (c) Saga Inc.\n * Distributed under the terms of the GNU Affero General Public License v3.0 License.\n */\n\n.chat-input-container {\n position: sticky;\n bottom: 0;\n margin: 10px 0;\n margin-top: auto;\n background-color: var(--chat-user-message-background-color);\n box-shadow: \n 0 4px 12px rgba(0, 0, 0, 0.08),\n 0 2px 4px rgba(0, 0, 0, 0.06),\n 0 0 0 1px rgba(0, 0, 0, 0.02);\n width: 100%;\n border-radius: 12px;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.chat-input-container.editing {\n margin-top: 0;\n}\n\n.chat-input-container.drag-over {\n border: 2px dashed var(--purple-500);\n transform: scale(1.02);\n}\n\n.chat-input-text-area-container {\n position: relative;\n height: min-content;\n}\n\n.chat-input {\n outline: none;\n border: none;\n resize: none;\n width: 100%;\n padding: 10px;\n overflow-y: auto;\n box-sizing: border-box;\n flex-shrink: 0 !important;\n background-color: var(--chat-user-message-background-color);\n font-size: 12px;\n font-weight: 400;\n font-family: var(--jp-ui-font-family);\n line-height: 1.2;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.active-cell-preview-container {\n padding: 10px;\n}\n\n.chat-input-container:focus-within {\n transform: translateY(-1px);\n box-shadow: \n 0 2px 8px rgba(0, 0, 0, 0.12),\n 0 8px 16px rgba(0, 0, 0, 0.08),\n 0 0 0 1px rgba(0, 0, 0, 0.04);\n}\n\n.chat-input:focus {\n color: var(--jp-ui-font-color1);\n}\n\n.chat-input::placeholder {\n color: var(--jp-ui-font-color2);\n transition: color 0.2s ease;\n}\n\n.chat-input:focus::placeholder {\n color: var(--jp-ui-font-color3);\n}\n\n.context-button {\n display: flex;\n align-items: center;\n background-color: var(--jp-layout-color2);\n border: 1px solid var(--jp-border-color1);\n border-radius: 3px;\n padding: 4px 8px;\n font-size: 12px;\n height: var(--chat-context-button-height);\n cursor: pointer;\n color: var(--jp-content-font-color1);\n transition: background-color 0.2s ease;\n}\n\n.context-button:hover {\n background-color: var(--jp-layout-color3);\n}\n\n/* Disabled state styles */\n.chat-input:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n background-color: var(--jp-layout-color2);\n}\n\n.context-button:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n background-color: var(--jp-layout-color2);\n}\n\n.context-button:disabled:hover {\n background-color: var(--jp-layout-color2);\n}"],"sourceRoot":""}]);
14601
14686
  // Exports
14602
14687
  /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);
14603
14688
 
@@ -20451,4 +20536,4 @@ var update = _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js
20451
20536
  /***/ })
20452
20537
 
20453
20538
  }]);
20454
- //# sourceMappingURL=lib_index_js.2db61d2b629817845901.js.map
20539
+ //# sourceMappingURL=lib_index_js.5c7d84a45ddeb5704b61.js.map