mito-ai 0.1.55__py3-none-any.whl → 0.1.56__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 (69) hide show
  1. mito_ai/_version.py +1 -1
  2. mito_ai/anthropic_client.py +7 -6
  3. mito_ai/completions/models.py +1 -1
  4. mito_ai/completions/prompt_builders/agent_execution_prompt.py +18 -50
  5. mito_ai/completions/prompt_builders/agent_smart_debug_prompt.py +77 -92
  6. mito_ai/completions/prompt_builders/agent_system_message.py +211 -275
  7. mito_ai/completions/prompt_builders/chat_prompt.py +15 -100
  8. mito_ai/completions/prompt_builders/chat_system_message.py +96 -72
  9. mito_ai/completions/prompt_builders/explain_code_prompt.py +22 -24
  10. mito_ai/completions/prompt_builders/inline_completer_prompt.py +78 -107
  11. mito_ai/completions/prompt_builders/prompt_constants.py +10 -48
  12. mito_ai/completions/prompt_builders/prompt_section_registry/__init__.py +70 -0
  13. mito_ai/completions/prompt_builders/prompt_section_registry/active_cell_code.py +15 -0
  14. mito_ai/completions/prompt_builders/prompt_section_registry/active_cell_id.py +10 -0
  15. mito_ai/completions/prompt_builders/prompt_section_registry/active_cell_output.py +20 -0
  16. mito_ai/completions/prompt_builders/prompt_section_registry/base.py +37 -0
  17. mito_ai/completions/prompt_builders/prompt_section_registry/error_traceback.py +17 -0
  18. mito_ai/completions/prompt_builders/prompt_section_registry/example.py +19 -0
  19. mito_ai/completions/prompt_builders/prompt_section_registry/files.py +17 -0
  20. mito_ai/completions/prompt_builders/prompt_section_registry/generic.py +15 -0
  21. mito_ai/completions/prompt_builders/prompt_section_registry/get_cell_output_tool_response.py +21 -0
  22. mito_ai/completions/prompt_builders/prompt_section_registry/notebook.py +19 -0
  23. mito_ai/completions/prompt_builders/prompt_section_registry/rules.py +39 -0
  24. mito_ai/completions/prompt_builders/{utils.py → prompt_section_registry/selected_context.py} +51 -42
  25. mito_ai/completions/prompt_builders/prompt_section_registry/streamlit_app_status.py +25 -0
  26. mito_ai/completions/prompt_builders/prompt_section_registry/task.py +12 -0
  27. mito_ai/completions/prompt_builders/prompt_section_registry/variables.py +18 -0
  28. mito_ai/completions/prompt_builders/smart_debug_prompt.py +48 -63
  29. mito_ai/constants.py +0 -3
  30. mito_ai/tests/completions/test_prompt_section_registry.py +44 -0
  31. mito_ai/tests/message_history/test_message_history_utils.py +273 -340
  32. mito_ai/tests/providers/test_anthropic_client.py +7 -3
  33. mito_ai/utils/message_history_utils.py +68 -44
  34. {mito_ai-0.1.55.data → mito_ai-0.1.56.data}/data/share/jupyter/labextensions/mito_ai/build_log.json +1 -1
  35. {mito_ai-0.1.55.data → mito_ai-0.1.56.data}/data/share/jupyter/labextensions/mito_ai/package.json +2 -2
  36. {mito_ai-0.1.55.data → mito_ai-0.1.56.data}/data/share/jupyter/labextensions/mito_ai/schemas/mito_ai/package.json.orig +1 -1
  37. mito_ai-0.1.55.data/data/share/jupyter/labextensions/mito_ai/static/lib_index_js.49c79c62671528877c61.js → mito_ai-0.1.56.data/data/share/jupyter/labextensions/mito_ai/static/lib_index_js.dfd7975de75d64db80d6.js +487 -120
  38. mito_ai-0.1.56.data/data/share/jupyter/labextensions/mito_ai/static/lib_index_js.dfd7975de75d64db80d6.js.map +1 -0
  39. mito_ai-0.1.55.data/data/share/jupyter/labextensions/mito_ai/static/remoteEntry.9dfbffc3592eb6f0aef9.js → mito_ai-0.1.56.data/data/share/jupyter/labextensions/mito_ai/static/remoteEntry.1e7b5cf362385f109883.js +3 -3
  40. mito_ai-0.1.55.data/data/share/jupyter/labextensions/mito_ai/static/remoteEntry.9dfbffc3592eb6f0aef9.js.map → mito_ai-0.1.56.data/data/share/jupyter/labextensions/mito_ai/static/remoteEntry.1e7b5cf362385f109883.js.map +1 -1
  41. {mito_ai-0.1.55.dist-info → mito_ai-0.1.56.dist-info}/METADATA +5 -1
  42. {mito_ai-0.1.55.dist-info → mito_ai-0.1.56.dist-info}/RECORD +68 -52
  43. mito_ai-0.1.55.data/data/share/jupyter/labextensions/mito_ai/static/lib_index_js.49c79c62671528877c61.js.map +0 -1
  44. {mito_ai-0.1.55.data → mito_ai-0.1.56.data}/data/etc/jupyter/jupyter_server_config.d/mito_ai.json +0 -0
  45. {mito_ai-0.1.55.data → mito_ai-0.1.56.data}/data/share/jupyter/labextensions/mito_ai/schemas/mito_ai/toolbar-buttons.json +0 -0
  46. {mito_ai-0.1.55.data → mito_ai-0.1.56.data}/data/share/jupyter/labextensions/mito_ai/static/node_modules_process_browser_js.4b128e94d31a81ebd209.js +0 -0
  47. {mito_ai-0.1.55.data → mito_ai-0.1.56.data}/data/share/jupyter/labextensions/mito_ai/static/node_modules_process_browser_js.4b128e94d31a81ebd209.js.map +0 -0
  48. {mito_ai-0.1.55.data → mito_ai-0.1.56.data}/data/share/jupyter/labextensions/mito_ai/static/style.js +0 -0
  49. {mito_ai-0.1.55.data → mito_ai-0.1.56.data}/data/share/jupyter/labextensions/mito_ai/static/style_index_js.f5d476ac514294615881.js +0 -0
  50. {mito_ai-0.1.55.data → mito_ai-0.1.56.data}/data/share/jupyter/labextensions/mito_ai/static/style_index_js.f5d476ac514294615881.js.map +0 -0
  51. {mito_ai-0.1.55.data → mito_ai-0.1.56.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
  52. {mito_ai-0.1.55.data → mito_ai-0.1.56.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
  53. {mito_ai-0.1.55.data → mito_ai-0.1.56.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
  54. {mito_ai-0.1.55.data → mito_ai-0.1.56.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
  55. {mito_ai-0.1.55.data → mito_ai-0.1.56.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_dist_esm_index_mjs.6bac1a8c4cc93f15f6b7.js +0 -0
  56. {mito_ai-0.1.55.data → mito_ai-0.1.56.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_dist_esm_index_mjs.6bac1a8c4cc93f15f6b7.js.map +0 -0
  57. {mito_ai-0.1.55.data → mito_ai-0.1.56.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_ui-react_dist_esm_index_mjs.4fcecd65bef9e9847609.js +0 -0
  58. {mito_ai-0.1.55.data → mito_ai-0.1.56.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_ui-react_dist_esm_index_mjs.4fcecd65bef9e9847609.js.map +0 -0
  59. {mito_ai-0.1.55.data → mito_ai-0.1.56.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
  60. {mito_ai-0.1.55.data → mito_ai-0.1.56.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
  61. {mito_ai-0.1.55.data → mito_ai-0.1.56.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_semver_index_js.3f6754ac5116d47de76b.js +0 -0
  62. {mito_ai-0.1.55.data → mito_ai-0.1.56.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_semver_index_js.3f6754ac5116d47de76b.js.map +0 -0
  63. {mito_ai-0.1.55.data → mito_ai-0.1.56.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_vscode-diff_dist_index_js.ea55f1f9346638aafbcf.js +0 -0
  64. {mito_ai-0.1.55.data → mito_ai-0.1.56.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_vscode-diff_dist_index_js.ea55f1f9346638aafbcf.js.map +0 -0
  65. {mito_ai-0.1.55.data → mito_ai-0.1.56.data}/data/share/jupyter/labextensions/mito_ai/themes/mito_ai/index.css +0 -0
  66. {mito_ai-0.1.55.data → mito_ai-0.1.56.data}/data/share/jupyter/labextensions/mito_ai/themes/mito_ai/index.js +0 -0
  67. {mito_ai-0.1.55.dist-info → mito_ai-0.1.56.dist-info}/WHEEL +0 -0
  68. {mito_ai-0.1.55.dist-info → mito_ai-0.1.56.dist-info}/entry_points.txt +0 -0
  69. {mito_ai-0.1.55.dist-info → mito_ai-0.1.56.dist-info}/licenses/LICENSE +0 -0
@@ -173,7 +173,7 @@ const AiChatPlugin = {
173
173
  // then call it to make a new widget
174
174
  const newWidget = () => {
175
175
  // Create a blank content widget inside of a MainAreaWidget
176
- const chatWidget = (0,_ChatWidget__WEBPACK_IMPORTED_MODULE_9__.buildChatWidget)(app, notebookTracker, rendermime, contextManager, streamlitPreviewManager);
176
+ const chatWidget = (0,_ChatWidget__WEBPACK_IMPORTED_MODULE_9__.buildChatWidget)(app, notebookTracker, rendermime, contextManager, streamlitPreviewManager, documentManager);
177
177
  return chatWidget;
178
178
  };
179
179
  let widget = newWidget();
@@ -1327,17 +1327,19 @@ __webpack_require__.r(__webpack_exports__);
1327
1327
  /* harmony export */ });
1328
1328
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "webpack/sharing/consume/default/react");
1329
1329
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
1330
- /* harmony import */ var _utils_classNames__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../../utils/classNames */ "./lib/utils/classNames.js");
1331
- /* harmony import */ var _ChatDropdown__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./ChatDropdown */ "./lib/Extensions/AiChat/ChatMessage/ChatDropdown.js");
1330
+ /* harmony import */ var _utils_classNames__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../../utils/classNames */ "./lib/utils/classNames.js");
1331
+ /* harmony import */ var _ChatDropdown__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./ChatDropdown */ "./lib/Extensions/AiChat/ChatMessage/ChatDropdown.js");
1332
1332
  /* harmony import */ var _utils_notebook__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../utils/notebook */ "./lib/utils/notebook.js");
1333
- /* harmony import */ var _utils_cellReferences__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../../utils/cellReferences */ "./lib/utils/cellReferences.js");
1333
+ /* harmony import */ var _utils_cellReferences__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../../utils/cellReferences */ "./lib/utils/cellReferences.js");
1334
1334
  /* harmony import */ var _style_ChatInput_css__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../style/ChatInput.css */ "./style/ChatInput.css");
1335
1335
  /* harmony import */ var _style_ChatDropdown_css__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../../style/ChatDropdown.css */ "./style/ChatDropdown.css");
1336
- /* harmony import */ var _hooks_useDebouncedFunction__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../../hooks/useDebouncedFunction */ "./lib/hooks/useDebouncedFunction.js");
1337
- /* harmony import */ var _components_SelectedContextContainer__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../../../components/SelectedContextContainer */ "./lib/components/SelectedContextContainer.js");
1338
- /* harmony import */ var _components_AttachFileButton__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../../components/AttachFileButton */ "./lib/components/AttachFileButton.js");
1339
- /* harmony import */ var _components_DatabaseButton__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../../components/DatabaseButton */ "./lib/components/DatabaseButton.js");
1340
- /* harmony import */ var _utils_fileUpload__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../../utils/fileUpload */ "./lib/utils/fileUpload.js");
1336
+ /* harmony import */ var _hooks_useDebouncedFunction__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../../hooks/useDebouncedFunction */ "./lib/hooks/useDebouncedFunction.js");
1337
+ /* harmony import */ var _hooks_useCellOrder__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../../hooks/useCellOrder */ "./lib/hooks/useCellOrder.js");
1338
+ /* harmony import */ var _hooks_useLineSelection__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../../hooks/useLineSelection */ "./lib/hooks/useLineSelection.js");
1339
+ /* harmony import */ var _components_SelectedContextContainer__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../../../components/SelectedContextContainer */ "./lib/components/SelectedContextContainer.js");
1340
+ /* harmony import */ var _components_AttachFileButton__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../../../components/AttachFileButton */ "./lib/components/AttachFileButton.js");
1341
+ /* harmony import */ var _components_DatabaseButton__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../../../components/DatabaseButton */ "./lib/components/DatabaseButton.js");
1342
+ /* harmony import */ var _utils_fileUpload__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../../utils/fileUpload */ "./lib/utils/fileUpload.js");
1341
1343
  /*
1342
1344
  * Copyright (c) Saga Inc.
1343
1345
  * Distributed under the terms of the GNU Affero General Public License v3.0 License.
@@ -1354,6 +1356,8 @@ __webpack_require__.r(__webpack_exports__);
1354
1356
 
1355
1357
 
1356
1358
 
1359
+
1360
+
1357
1361
  const ChatInput = ({ app, initialContent, handleSubmitUserMessage, onCancel, isEditing, contextManager, notebookTracker, agentModeEnabled = false, agentExecutionStatus = 'idle', operatingSystem = 'mac', displayOptimizedChatHistoryLength = 0, agentTargetNotebookPanelRef, isSignedUp = true, messageIndex, }) => {
1358
1362
  var _a;
1359
1363
  const [input, setInput] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(initialContent);
@@ -1366,6 +1370,9 @@ const ChatInput = ({ app, initialContent, handleSubmitUserMessage, onCancel, isE
1366
1370
  const [isDropdownFromButton, setIsDropdownFromButton] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false);
1367
1371
  const [isDragOver, setIsDragOver] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false);
1368
1372
  const [isUploading, setIsUploading] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false);
1373
+ // Track cell order and line selection
1374
+ const cellOrder = (0,_hooks_useCellOrder__WEBPACK_IMPORTED_MODULE_4__.useCellOrder)(notebookTracker);
1375
+ const lineSelection = (0,_hooks_useLineSelection__WEBPACK_IMPORTED_MODULE_5__.useLineSelection)(notebookTracker, cellOrder);
1369
1376
  const handleFileUpload = (file) => {
1370
1377
  let uploadType;
1371
1378
  if (file.type.startsWith('image/')) {
@@ -1409,7 +1416,7 @@ const ChatInput = ({ app, initialContent, handleSubmitUserMessage, onCancel, isE
1409
1416
  setIsUploading(true);
1410
1417
  try {
1411
1418
  // Upload all files to backend using the shared utility
1412
- const uploadPromises = Array.from(files).map(file => (0,_utils_fileUpload__WEBPACK_IMPORTED_MODULE_4__.uploadFileToBackend)(file, notebookTracker, handleFileUpload));
1419
+ const uploadPromises = Array.from(files).map(file => (0,_utils_fileUpload__WEBPACK_IMPORTED_MODULE_6__.uploadFileToBackend)(file, notebookTracker, handleFileUpload));
1413
1420
  // Use allSettled so we wait for all uploads to finish (success or failure)
1414
1421
  // before clearing the uploading state. This avoids background uploads
1415
1422
  // mutating state after isUploading becomes false.
@@ -1420,9 +1427,41 @@ const ChatInput = ({ app, initialContent, handleSubmitUserMessage, onCancel, isE
1420
1427
  }
1421
1428
  }
1422
1429
  };
1430
+ const handlePaste = async (e) => {
1431
+ const items = e.clipboardData.items;
1432
+ const clipboardItem = items === null || items === void 0 ? void 0 : items[items.length - 1];
1433
+ if (!clipboardItem)
1434
+ return;
1435
+ // Check if it's a file (images are also files)
1436
+ if (clipboardItem.kind === 'file') {
1437
+ e.preventDefault();
1438
+ const blob = clipboardItem.getAsFile();
1439
+ if (!blob)
1440
+ return;
1441
+ // Determine file name - use blob name if available, otherwise generate one
1442
+ let fileName = blob.name;
1443
+ if (!fileName) {
1444
+ // Generate a filename based on the MIME type
1445
+ const extension = clipboardItem.type.startsWith('image/')
1446
+ ? clipboardItem.type.split('/')[1]
1447
+ : 'file';
1448
+ fileName = `pasted-${Date.now()}.${extension}`;
1449
+ }
1450
+ const file = new File([blob], fileName, { type: clipboardItem.type });
1451
+ if (isUploading)
1452
+ return; // Prevent multiple simultaneous uploads
1453
+ setIsUploading(true);
1454
+ try {
1455
+ await (0,_utils_fileUpload__WEBPACK_IMPORTED_MODULE_6__.uploadFileToBackend)(file, notebookTracker, handleFileUpload);
1456
+ }
1457
+ finally {
1458
+ setIsUploading(false);
1459
+ }
1460
+ }
1461
+ };
1423
1462
  // Debounce the active cell ID change to avoid multiple rerenders.
1424
1463
  // We use this to avoid a flickering screen when the active cell changes.
1425
- const debouncedSetActiveCellID = (0,_hooks_useDebouncedFunction__WEBPACK_IMPORTED_MODULE_5__.useDebouncedFunction)((newID) => {
1464
+ const debouncedSetActiveCellID = (0,_hooks_useDebouncedFunction__WEBPACK_IMPORTED_MODULE_7__.useDebouncedFunction)((newID) => {
1426
1465
  setActiveCellID(newID);
1427
1466
  }, 100);
1428
1467
  (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {
@@ -1592,7 +1631,7 @@ const ChatInput = ({ app, initialContent, handleSubmitUserMessage, onCancel, isE
1592
1631
  };
1593
1632
  // Convert @Cell N references to [MITO_CELL_REF:cell_id] format before submitting
1594
1633
  const processMessageForSubmission = (messageText) => {
1595
- return (0,_utils_cellReferences__WEBPACK_IMPORTED_MODULE_6__.convertCellReferencesToStableFormat)(messageText, notebookTracker.currentWidget);
1634
+ return (0,_utils_cellReferences__WEBPACK_IMPORTED_MODULE_8__.convertCellReferencesToStableFormat)(messageText, notebookTracker.currentWidget);
1596
1635
  };
1597
1636
  const getExpandedVarialbes = () => {
1598
1637
  const activeNotebookContext = contextManager === null || contextManager === void 0 ? void 0 : contextManager.getActiveNotebookContext();
@@ -1680,13 +1719,58 @@ const ChatInput = ({ app, initialContent, handleSubmitUserMessage, onCancel, isE
1680
1719
  }
1681
1720
  }
1682
1721
  }, [agentModeEnabled, additionalContext, activeCellCode]);
1683
- return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: (0,_utils_classNames__WEBPACK_IMPORTED_MODULE_7__.classNames)("chat-input-container", {
1722
+ // Manage line selection context - shows selected lines when user has text selected in a code cell
1723
+ (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {
1724
+ const LINE_SELECTION_TYPE = 'line_selection';
1725
+ // Build the new value data for comparison (lines are 0-indexed internally)
1726
+ const newValueData = lineSelection.hasSelection
1727
+ ? JSON.stringify({
1728
+ cellId: lineSelection.cellId,
1729
+ startLine: lineSelection.startLine,
1730
+ endLine: lineSelection.endLine,
1731
+ selectedCode: lineSelection.selectedCode
1732
+ })
1733
+ : null;
1734
+ // Treat null and undefined as the same "no selection" state
1735
+ const normalizedNewValue = newValueData !== null && newValueData !== void 0 ? newValueData : null;
1736
+ setAdditionalContext(prev => {
1737
+ var _a;
1738
+ // Find existing line selection context in the latest state (avoid stale render closures)
1739
+ const existingContext = prev.find(context => context.type === LINE_SELECTION_TYPE);
1740
+ const normalizedExistingValue = (_a = existingContext === null || existingContext === void 0 ? void 0 : existingContext.value) !== null && _a !== void 0 ? _a : null;
1741
+ // Only update if the selection has changed (null and undefined are equivalent)
1742
+ if (normalizedNewValue === normalizedExistingValue) {
1743
+ return prev;
1744
+ }
1745
+ // Remove old line selection context if it exists
1746
+ let additionalContextCopy = prev.filter(context => context.type !== LINE_SELECTION_TYPE);
1747
+ // Add new line selection context if there is text selected
1748
+ if (normalizedNewValue) {
1749
+ // Build display text with 1-indexed lines for user display
1750
+ const displayStartLine = lineSelection.startLine + 1;
1751
+ const displayEndLine = lineSelection.endLine + 1;
1752
+ const displayText = displayStartLine === displayEndLine
1753
+ ? `Cell ${lineSelection.cellNumber} line ${displayStartLine}`
1754
+ : `Cell ${lineSelection.cellNumber} line ${displayStartLine}-${displayEndLine}`;
1755
+ additionalContextCopy = [
1756
+ ...additionalContextCopy,
1757
+ {
1758
+ type: LINE_SELECTION_TYPE,
1759
+ value: normalizedNewValue,
1760
+ display: displayText
1761
+ }
1762
+ ];
1763
+ }
1764
+ return additionalContextCopy;
1765
+ });
1766
+ }, [lineSelection]);
1767
+ return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: (0,_utils_classNames__WEBPACK_IMPORTED_MODULE_9__.classNames)("chat-input-container", {
1684
1768
  "editing": isEditing,
1685
1769
  "drag-over": isDragOver
1686
1770
  }), onDragOver: handleDragOver, onDragLeave: handleDragLeave, onDrop: handleDrop },
1687
1771
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: 'context-container' },
1688
- react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_DatabaseButton__WEBPACK_IMPORTED_MODULE_8__["default"], { app: app }),
1689
- react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_AttachFileButton__WEBPACK_IMPORTED_MODULE_9__["default"], { onFileUploaded: handleFileUpload, notebookTracker: notebookTracker }),
1772
+ react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_DatabaseButton__WEBPACK_IMPORTED_MODULE_10__["default"], { app: app }),
1773
+ react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_AttachFileButton__WEBPACK_IMPORTED_MODULE_11__["default"], { onFileUploaded: handleFileUpload, notebookTracker: notebookTracker }),
1690
1774
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement("button", { className: "context-button", onClick: () => {
1691
1775
  var _a;
1692
1776
  setDropdownVisible(true);
@@ -1694,9 +1778,9 @@ const ChatInput = ({ app, initialContent, handleSubmitUserMessage, onCancel, isE
1694
1778
  setIsDropdownFromButton(true);
1695
1779
  (_a = textAreaRef.current) === null || _a === void 0 ? void 0 : _a.focus();
1696
1780
  } }, "\uFF20 Add Context"),
1697
- additionalContext.map((context, index) => (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_SelectedContextContainer__WEBPACK_IMPORTED_MODULE_10__["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, value: context.value })))),
1781
+ additionalContext.map((context, index) => (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_SelectedContextContainer__WEBPACK_IMPORTED_MODULE_12__["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, value: context.value })))),
1698
1782
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: 'chat-input-text-area-container' },
1699
- react__WEBPACK_IMPORTED_MODULE_0___default().createElement("textarea", { ref: textAreaRef, className: (0,_utils_classNames__WEBPACK_IMPORTED_MODULE_7__.classNames)("message", "message-user", 'chat-input', { "agent-mode": agentModeEnabled }), placeholder: getPlaceholderText(), value: input, disabled: agentExecutionStatus === 'working' || agentExecutionStatus === 'stopping', onChange: handleInputChange, onKeyDown: (e) => {
1783
+ react__WEBPACK_IMPORTED_MODULE_0___default().createElement("textarea", { ref: textAreaRef, className: (0,_utils_classNames__WEBPACK_IMPORTED_MODULE_9__.classNames)("message", "message-user", 'chat-input', { "agent-mode": agentModeEnabled }), placeholder: getPlaceholderText(), value: input, disabled: agentExecutionStatus === 'working' || agentExecutionStatus === 'stopping', onChange: handleInputChange, onPaste: handlePaste, onKeyDown: (e) => {
1700
1784
  // If dropdown is visible, only handle escape to close it
1701
1785
  if (isDropdownVisible) {
1702
1786
  if (e.key === 'Escape') {
@@ -1725,7 +1809,7 @@ const ChatInput = ({ app, initialContent, handleSubmitUserMessage, onCancel, isE
1725
1809
  }
1726
1810
  }
1727
1811
  } }),
1728
- isDropdownVisible && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_ChatDropdown__WEBPACK_IMPORTED_MODULE_11__["default"], { options: getExpandedVarialbes(), onSelect: handleOptionSelect, filterText: dropdownFilter, isDropdownFromButton: isDropdownFromButton, onFilterChange: setDropdownFilter, onClose: handleDropdownClose, notebookTracker: notebookTracker }))),
1812
+ isDropdownVisible && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_ChatDropdown__WEBPACK_IMPORTED_MODULE_13__["default"], { options: getExpandedVarialbes(), onSelect: handleOptionSelect, filterText: dropdownFilter, isDropdownFromButton: isDropdownFromButton, onFilterChange: setDropdownFilter, onClose: handleDropdownClose, notebookTracker: notebookTracker }))),
1729
1813
  isEditing &&
1730
1814
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: "message-edit-buttons" },
1731
1815
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement("button", { onClick: () => {
@@ -1752,14 +1836,14 @@ __webpack_require__.r(__webpack_exports__);
1752
1836
  /* harmony export */ });
1753
1837
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "webpack/sharing/consume/default/react");
1754
1838
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
1755
- /* harmony import */ var _utils_classNames__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../../utils/classNames */ "./lib/utils/classNames.js");
1756
- /* harmony import */ var _UserCodeBlock__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./UserCodeBlock */ "./lib/Extensions/AiChat/ChatMessage/UserCodeBlock.js");
1757
- /* harmony import */ var _AssistantCodeBlock__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./AssistantCodeBlock */ "./lib/Extensions/AiChat/ChatMessage/AssistantCodeBlock.js");
1758
- /* harmony import */ var _AlertBlock__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./AlertBlock */ "./lib/Extensions/AiChat/ChatMessage/AlertBlock.js");
1839
+ /* harmony import */ var _utils_classNames__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../../utils/classNames */ "./lib/utils/classNames.js");
1840
+ /* harmony import */ var _UserCodeBlock__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./UserCodeBlock */ "./lib/Extensions/AiChat/ChatMessage/UserCodeBlock.js");
1841
+ /* harmony import */ var _AssistantCodeBlock__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./AssistantCodeBlock */ "./lib/Extensions/AiChat/ChatMessage/AssistantCodeBlock.js");
1842
+ /* harmony import */ var _AlertBlock__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./AlertBlock */ "./lib/Extensions/AiChat/ChatMessage/AlertBlock.js");
1759
1843
  /* harmony import */ var _MarkdownBlock__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./MarkdownBlock */ "./lib/Extensions/AiChat/ChatMessage/MarkdownBlock.js");
1760
- /* harmony import */ var _utils_strings__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../../utils/strings */ "./lib/utils/strings.js");
1844
+ /* harmony import */ var _utils_strings__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../utils/strings */ "./lib/utils/strings.js");
1761
1845
  /* harmony import */ var _icons_Pencil__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ../../../icons/Pencil */ "./lib/icons/Pencil.js");
1762
- /* harmony import */ var _ChatInput__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./ChatInput */ "./lib/Extensions/AiChat/ChatMessage/ChatInput.js");
1846
+ /* harmony import */ var _ChatInput__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./ChatInput */ "./lib/Extensions/AiChat/ChatMessage/ChatInput.js");
1763
1847
  /* harmony import */ var _components_TextAndIconButton__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../../../components/TextAndIconButton */ "./lib/components/TextAndIconButton.js");
1764
1848
  /* harmony import */ var _icons_PlayButtonIcon__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../../../icons/PlayButtonIcon */ "./lib/icons/PlayButtonIcon.js");
1765
1849
  /* harmony import */ var _icons_CopyIcon__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../../../icons/CopyIcon */ "./lib/icons/CopyIcon.js");
@@ -1767,7 +1851,7 @@ __webpack_require__.r(__webpack_exports__);
1767
1851
  /* harmony import */ var _components_TextButton__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../../../components/TextButton */ "./lib/components/TextButton.js");
1768
1852
  /* harmony import */ var _style_ChatMessage_css__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../style/ChatMessage.css */ "./style/ChatMessage.css");
1769
1853
  /* harmony import */ var _style_MarkdownMessage_css__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../../style/MarkdownMessage.css */ "./style/MarkdownMessage.css");
1770
- /* harmony import */ var _utils_notebook__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../utils/notebook */ "./lib/utils/notebook.js");
1854
+ /* harmony import */ var _cellUpdateUtils__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../cellUpdateUtils */ "./lib/Extensions/AiChat/cellUpdateUtils.js");
1771
1855
  /* harmony import */ var _components_AgentComponents_GetCellOutputToolUI__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ../../../components/AgentComponents/GetCellOutputToolUI */ "./lib/components/AgentComponents/GetCellOutputToolUI.js");
1772
1856
  /* harmony import */ var _components_AgentComponents_AssumptionToolUI__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ../../../components/AgentComponents/AssumptionToolUI */ "./lib/components/AgentComponents/AssumptionToolUI.js");
1773
1857
  /* harmony import */ var _components_SelectedContextContainer__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../../../components/SelectedContextContainer */ "./lib/components/SelectedContextContainer.js");
@@ -1801,24 +1885,14 @@ __webpack_require__.r(__webpack_exports__);
1801
1885
 
1802
1886
 
1803
1887
 
1804
- const getCellIdFromCellUpdate = (cellUpdate, notebookTracker) => {
1805
- if (!cellUpdate) {
1806
- return undefined;
1807
- }
1808
- if (cellUpdate.type === 'modification') {
1809
- return cellUpdate.id;
1810
- }
1811
- // For 'new' type, get the cell ID by index
1812
- return (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_3__.getCellIDByIndexInNotebookPanel)(notebookTracker.currentWidget, cellUpdate.index);
1813
- };
1814
1888
  const ChatMessage = ({ app, message, promptType, agentResponse, messageIndex, mitoAIConnectionError, mitoAIConnectionErrorType, notebookTracker, renderMimeRegistry, isLastAiMessage, isLastMessage, operatingSystem, previewAICode, acceptAICode, rejectAICode, contextManager, codeReviewStatus, setNextSteps, agentModeEnabled, additionalContext, handleSubmitUserMessage, }) => {
1815
1889
  const [isEditing, setIsEditing] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false);
1816
1890
  if (message.role !== 'user' && message.role !== 'assistant') {
1817
1891
  return null;
1818
1892
  }
1819
1893
  const editable = message.role === 'user';
1820
- const messageContentParts = (0,_utils_strings__WEBPACK_IMPORTED_MODULE_4__.splitStringWithCodeBlocks)(message);
1821
- const messageContent = (0,_utils_strings__WEBPACK_IMPORTED_MODULE_4__.getContentStringFromMessage)(message);
1894
+ const messageContentParts = (0,_utils_strings__WEBPACK_IMPORTED_MODULE_3__.splitStringWithCodeBlocks)(message);
1895
+ const messageContent = (0,_utils_strings__WEBPACK_IMPORTED_MODULE_3__.getContentStringFromMessage)(message);
1822
1896
  const handleEditClick = () => {
1823
1897
  setIsEditing(true);
1824
1898
  };
@@ -1841,11 +1915,11 @@ const ChatMessage = ({ app, message, promptType, agentResponse, messageIndex, mi
1841
1915
  setNextSteps(agentResponse.next_steps);
1842
1916
  }
1843
1917
  if (isEditing) {
1844
- return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_ChatInput__WEBPACK_IMPORTED_MODULE_5__["default"], { app: app, initialContent: message.content.replace(/```[\s\S]*?```/g, '').trim(), onCancel: handleCancel, isEditing: isEditing, contextManager: contextManager, notebookTracker: notebookTracker, agentModeEnabled: false, handleSubmitUserMessage: handleSubmitUserMessageAndCloseEditing, messageIndex: messageIndex }));
1918
+ return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_ChatInput__WEBPACK_IMPORTED_MODULE_4__["default"], { app: app, initialContent: message.content.replace(/```[\s\S]*?```/g, '').trim(), onCancel: handleCancel, isEditing: isEditing, contextManager: contextManager, notebookTracker: notebookTracker, agentModeEnabled: false, handleSubmitUserMessage: handleSubmitUserMessageAndCloseEditing, messageIndex: messageIndex }));
1845
1919
  }
1846
1920
  if (mitoAIConnectionError) {
1847
- return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: (0,_utils_classNames__WEBPACK_IMPORTED_MODULE_6__.classNames)("message") },
1848
- react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_AlertBlock__WEBPACK_IMPORTED_MODULE_7__["default"], { content: message.content, mitoAIConnectionErrorType: mitoAIConnectionErrorType })));
1921
+ return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: (0,_utils_classNames__WEBPACK_IMPORTED_MODULE_5__.classNames)("message") },
1922
+ react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_AlertBlock__WEBPACK_IMPORTED_MODULE_6__["default"], { content: message.content, mitoAIConnectionErrorType: mitoAIConnectionErrorType })));
1849
1923
  }
1850
1924
  // If the message is empty, don't render anything
1851
1925
  if (messageContent === undefined || messageContent === '') {
@@ -1855,16 +1929,16 @@ const ChatMessage = ({ app, message, promptType, agentResponse, messageIndex, mi
1855
1929
  // Users end up applying the code in the middle of streaming and it gets very confusing
1856
1930
  // very quickly for users.
1857
1931
  let isCodeComplete = false;
1858
- return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: (0,_utils_classNames__WEBPACK_IMPORTED_MODULE_6__.classNames)("message", { "message-user": message.role === 'user' }, { 'message-assistant-chat': message.role === 'assistant' }) },
1932
+ return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: (0,_utils_classNames__WEBPACK_IMPORTED_MODULE_5__.classNames)("message", { "message-user": message.role === 'user' }, { 'message-assistant-chat': message.role === 'assistant' }) },
1859
1933
  messageContentParts.map((messagePart, index) => {
1860
1934
  var _a, _b;
1861
- if (messagePart.startsWith(_utils_strings__WEBPACK_IMPORTED_MODULE_4__.PYTHON_CODE_BLOCK_START_WITHOUT_NEW_LINE)) {
1935
+ if (messagePart.startsWith(_utils_strings__WEBPACK_IMPORTED_MODULE_3__.PYTHON_CODE_BLOCK_START_WITHOUT_NEW_LINE)) {
1862
1936
  isCodeComplete = messagePart.endsWith('```');
1863
1937
  // Make sure that there is actually code in the message.
1864
1938
  // An empty code will look like this '```python ```'
1865
1939
  if (messagePart.length > 14) {
1866
1940
  return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null,
1867
- message.role === 'user' ? (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_UserCodeBlock__WEBPACK_IMPORTED_MODULE_8__["default"], { code: messagePart, renderMimeRegistry: renderMimeRegistry, agentModeEnabled: agentModeEnabled })) : (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_AssistantCodeBlock__WEBPACK_IMPORTED_MODULE_9__["default"], { code: messagePart, codeSummary: (_b = (_a = agentResponse === null || agentResponse === void 0 ? void 0 : agentResponse.cell_update) === null || _a === void 0 ? void 0 : _a.code_summary) !== null && _b !== void 0 ? _b : ((agentResponse === null || agentResponse === void 0 ? void 0 : agentResponse.type) === 'run_all_cells' ? 'Running all cells' : undefined), isCodeComplete: isCodeComplete, renderMimeRegistry: renderMimeRegistry, previewAICode: previewAICode, acceptAICode: acceptAICode, rejectAICode: rejectAICode, isLastAiMessage: isLastAiMessage, codeReviewStatus: codeReviewStatus, agentModeEnabled: agentModeEnabled, cellId: getCellIdFromCellUpdate(agentResponse === null || agentResponse === void 0 ? void 0 : agentResponse.cell_update, notebookTracker), notebookPanel: notebookTracker.currentWidget })),
1941
+ message.role === 'user' ? (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_UserCodeBlock__WEBPACK_IMPORTED_MODULE_7__["default"], { code: messagePart, renderMimeRegistry: renderMimeRegistry, agentModeEnabled: agentModeEnabled })) : (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_AssistantCodeBlock__WEBPACK_IMPORTED_MODULE_8__["default"], { code: messagePart, codeSummary: (_b = (_a = agentResponse === null || agentResponse === void 0 ? void 0 : agentResponse.cell_update) === null || _a === void 0 ? void 0 : _a.code_summary) !== null && _b !== void 0 ? _b : ((agentResponse === null || agentResponse === void 0 ? void 0 : agentResponse.type) === 'run_all_cells' ? 'Running all cells' : undefined), isCodeComplete: isCodeComplete, renderMimeRegistry: renderMimeRegistry, previewAICode: previewAICode, acceptAICode: acceptAICode, rejectAICode: rejectAICode, isLastAiMessage: isLastAiMessage, codeReviewStatus: codeReviewStatus, agentModeEnabled: agentModeEnabled, cellId: (0,_cellUpdateUtils__WEBPACK_IMPORTED_MODULE_9__.getCellIdFromCellUpdate)(agentResponse === null || agentResponse === void 0 ? void 0 : agentResponse.cell_update, notebookTracker), notebookPanel: notebookTracker.currentWidget })),
1868
1942
  !agentModeEnabled && isLastAiMessage && isCodeComplete && codeReviewStatus === 'chatPreview' &&
1869
1943
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: 'chat-message-buttons' },
1870
1944
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_TextAndIconButton__WEBPACK_IMPORTED_MODULE_10__["default"], { onClick: () => { previewAICode(); }, text: 'Overwrite Active Cell', icon: _icons_PlayButtonIcon__WEBPACK_IMPORTED_MODULE_11__["default"], title: 'Write the Ai generated code to the active cell in the jupyter notebook, replacing the current code.', variant: 'gray', width: 'fit-contents' }),
@@ -1884,7 +1958,7 @@ const ChatMessage = ({ app, message, promptType, agentResponse, messageIndex, mi
1884
1958
  }
1885
1959
  }
1886
1960
  else {
1887
- return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { key: index + messagePart, className: (0,_utils_classNames__WEBPACK_IMPORTED_MODULE_6__.classNames)('markdown-message-part') },
1961
+ return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { key: index + messagePart, className: (0,_utils_classNames__WEBPACK_IMPORTED_MODULE_5__.classNames)('markdown-message-part') },
1888
1962
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement("p", { onDoubleClick: () => {
1889
1963
  // Only allow users to edit their own messages, not the AI responses
1890
1964
  if (message.role === 'user') {
@@ -2526,8 +2600,8 @@ __webpack_require__.r(__webpack_exports__);
2526
2600
  /* harmony import */ var _utils_chatHistory__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! ../../utils/chatHistory */ "./lib/utils/chatHistory.js");
2527
2601
  /* harmony import */ var _utils_codeDiff__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ../../utils/codeDiff */ "./lib/utils/codeDiff.js");
2528
2602
  /* harmony import */ var _utils_cellOutput__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ../../utils/cellOutput */ "./lib/utils/cellOutput.js");
2529
- /* harmony import */ var _utils_waitForNotebookReady__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ../../utils/waitForNotebookReady */ "./lib/utils/waitForNotebookReady.js");
2530
2603
  /* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./utils */ "./lib/Extensions/AiChat/utils.js");
2604
+ /* harmony import */ var _utils_waitForNotebookReady__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ../../utils/waitForNotebookReady */ "./lib/utils/waitForNotebookReady.js");
2531
2605
  /* harmony import */ var _restAPI_RestAPI__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ../../restAPI/RestAPI */ "./lib/restAPI/RestAPI.js");
2532
2606
  /* harmony import */ var _utils_sound__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ../../utils/sound */ "./lib/utils/sound.js");
2533
2607
  /* harmony import */ var _SettingsManager_SettingsManagerPlugin__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(/*! ../SettingsManager/SettingsManagerPlugin */ "./lib/Extensions/SettingsManager/SettingsManagerPlugin.js");
@@ -2586,6 +2660,7 @@ __webpack_require__.r(__webpack_exports__);
2586
2660
 
2587
2661
 
2588
2662
 
2663
+
2589
2664
  // Internal imports - Chat components
2590
2665
 
2591
2666
 
@@ -2617,7 +2692,7 @@ const getDefaultChatHistoryManager = (notebookTracker, contextManager, app) => {
2617
2692
  const chatHistoryManager = new _ChatHistoryManager__WEBPACK_IMPORTED_MODULE_6__.ChatHistoryManager(contextManager, notebookTracker, app);
2618
2693
  return chatHistoryManager;
2619
2694
  };
2620
- const ChatTaskpane = ({ notebookTracker, renderMimeRegistry, contextManager, streamlitPreviewManager, app, operatingSystem, websocketClient, }) => {
2695
+ const ChatTaskpane = ({ notebookTracker, renderMimeRegistry, contextManager, streamlitPreviewManager, app, operatingSystem, websocketClient, documentManager, }) => {
2621
2696
  // User signup state
2622
2697
  const { isSignedUp, refreshUserSignupState } = (0,_hooks_useUserSignup__WEBPACK_IMPORTED_MODULE_7__.useUserSignup)();
2623
2698
  // Core chat state management
@@ -2779,21 +2854,17 @@ const ChatTaskpane = ({ notebookTracker, renderMimeRegistry, contextManager, str
2779
2854
  const sendAgentExecutionMessage = async (input, messageIndex, sendCellIDOutput = undefined, additionalContext) => {
2780
2855
  // Step 0: reset the state for a new message
2781
2856
  resetForNewMessage();
2782
- const agentTargetNotebookPanel = agentTargetNotebookPanelRef.current;
2783
- if (agentTargetNotebookPanel === null) {
2784
- return;
2785
- }
2786
2857
  // Step 1: Add the user's message to the chat history
2787
2858
  const newChatHistoryManager = getDuplicateChatHistoryManager();
2788
2859
  if (messageIndex !== undefined) {
2789
2860
  // Drop all of the messages starting at the message index
2790
2861
  newChatHistoryManager.dropMessagesStartingAtIndex(messageIndex);
2791
2862
  }
2792
- const agentExecutionMetadata = newChatHistoryManager.addAgentExecutionMessage(activeThreadIdRef.current, agentTargetNotebookPanel, input, additionalContext);
2863
+ const agentExecutionMetadata = newChatHistoryManager.addAgentExecutionMessage(activeThreadIdRef.current, agentTargetNotebookPanelRef.current, input, additionalContext);
2793
2864
  if (messageIndex !== undefined) {
2794
2865
  agentExecutionMetadata.index = messageIndex;
2795
2866
  }
2796
- agentExecutionMetadata.base64EncodedActiveCellOutput = await (0,_utils__WEBPACK_IMPORTED_MODULE_17__.getBase64EncodedCellOutputInNotebook)(agentTargetNotebookPanel, sendCellIDOutput);
2867
+ agentExecutionMetadata.base64EncodedActiveCellOutput = await (0,_utils__WEBPACK_IMPORTED_MODULE_17__.getBase64EncodedCellOutputInNotebook)(agentTargetNotebookPanelRef.current, sendCellIDOutput);
2797
2868
  setChatHistoryManager(newChatHistoryManager);
2798
2869
  setLoadingStatus('thinking');
2799
2870
  // Step 2: Send the message to the AI
@@ -2811,6 +2882,8 @@ const ChatTaskpane = ({ notebookTracker, renderMimeRegistry, contextManager, str
2811
2882
  const sendChatInputMessage = async (input, messageIndex, additionalContext) => {
2812
2883
  // Step 0: reset the state for a new message
2813
2884
  resetForNewMessage();
2885
+ // Ensure a notebook exists before proceeding
2886
+ await (0,_utils__WEBPACK_IMPORTED_MODULE_17__.ensureNotebookExists)(notebookTracker, documentManager);
2814
2887
  // Enable follow mode when user sends a new message
2815
2888
  setAutoScrollFollowMode(true);
2816
2889
  // Step 1: Add the user's message to the chat history
@@ -3004,6 +3077,7 @@ const ChatTaskpane = ({ notebookTracker, renderMimeRegistry, contextManager, str
3004
3077
  app,
3005
3078
  streamlitPreviewManager,
3006
3079
  websocketClient,
3080
+ documentManager,
3007
3081
  chatHistoryManagerRef,
3008
3082
  activeThreadIdRef,
3009
3083
  activeRequestControllerRef,
@@ -3146,6 +3220,24 @@ const ChatTaskpane = ({ notebookTracker, renderMimeRegistry, contextManager, str
3146
3220
  execute: rejectAICode,
3147
3221
  isVisible: () => (0,_utils_codeDiff__WEBPACK_IMPORTED_MODULE_26__.shouldShowDiffToolbarButtons)(notebookTracker, cellStateBeforeDiff.current, agentReview.changedCellsRef.current)
3148
3222
  });
3223
+ /*
3224
+ Register global command for starting a new chat.
3225
+ This can be triggered from anywhere with CMD+K (Mac) or Ctrl+K (Windows/Linux).
3226
+ */
3227
+ app.commands.addCommand(_commands__WEBPACK_IMPORTED_MODULE_13__.COMMAND_MITO_AI_START_NEW_CHAT, {
3228
+ label: 'Start New Chat',
3229
+ execute: async () => {
3230
+ await startNewChat();
3231
+ // Focus the chat input after starting new chat
3232
+ const chatInput = document.querySelector('.chat-input');
3233
+ chatInput === null || chatInput === void 0 ? void 0 : chatInput.focus();
3234
+ }
3235
+ });
3236
+ app.commands.addKeyBinding({
3237
+ command: _commands__WEBPACK_IMPORTED_MODULE_13__.COMMAND_MITO_AI_START_NEW_CHAT,
3238
+ keys: ['Accel K'],
3239
+ selector: 'body',
3240
+ });
3149
3241
  }, []);
3150
3242
  (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {
3151
3243
  // Register keyboard shortcuts
@@ -3217,7 +3309,7 @@ const ChatTaskpane = ({ notebookTracker, renderMimeRegistry, contextManager, str
3217
3309
  } }),
3218
3310
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_UsageBadge__WEBPACK_IMPORTED_MODULE_31__["default"], { app: app, ref: usageBadgeRef })),
3219
3311
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: "chat-taskpane-header-right" },
3220
- react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_IconButton__WEBPACK_IMPORTED_MODULE_29__["default"], { icon: react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_jupyterlab_ui_components__WEBPACK_IMPORTED_MODULE_1__.addIcon.react, null), title: "Start New Chat", onClick: async () => { await startNewChat(); } }),
3312
+ react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_IconButton__WEBPACK_IMPORTED_MODULE_29__["default"], { icon: react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_jupyterlab_ui_components__WEBPACK_IMPORTED_MODULE_1__.addIcon.react, null), title: `Start New Chat (${operatingSystem === 'mac' ? '⌘' : 'Ctrl'}K)`, onClick: async () => { await startNewChat(); } }),
3221
3313
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_DropdownMenu__WEBPACK_IMPORTED_MODULE_32__["default"], { trigger: react__WEBPACK_IMPORTED_MODULE_0___default().createElement("button", { className: "icon-button", title: "Chat Threads", onClick: fetchChatThreads },
3222
3314
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_jupyterlab_ui_components__WEBPACK_IMPORTED_MODULE_1__.historyIcon.react, null)), items: chatThreads.length > 0
3223
3315
  ? chatThreads.map(thread => ({
@@ -3398,7 +3490,7 @@ class ChatWidget extends _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_1__.React
3398
3490
  super.dispose();
3399
3491
  }
3400
3492
  render() {
3401
- return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_ChatTaskpane__WEBPACK_IMPORTED_MODULE_6__["default"], { app: this.options.app, notebookTracker: this.options.notebookTracker, renderMimeRegistry: this.options.renderMimeRegistry, contextManager: this.options.contextManager, streamlitPreviewManager: this.options.streamlitPreviewManager, operatingSystem: this.options.operatingSystem, websocketClient: this.websocketClient }));
3493
+ return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_ChatTaskpane__WEBPACK_IMPORTED_MODULE_6__["default"], { app: this.options.app, notebookTracker: this.options.notebookTracker, renderMimeRegistry: this.options.renderMimeRegistry, contextManager: this.options.contextManager, streamlitPreviewManager: this.options.streamlitPreviewManager, operatingSystem: this.options.operatingSystem, websocketClient: this.websocketClient, documentManager: this.options.documentManager }));
3402
3494
  }
3403
3495
  onMessage(client, message) {
3404
3496
  switch (message.type) {
@@ -3411,7 +3503,7 @@ class ChatWidget extends _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_1__.React
3411
3503
  }
3412
3504
  }
3413
3505
  }
3414
- function buildChatWidget(app, notebookTracker, renderMimeRegistry, contextManager, streamlitPreviewManager) {
3506
+ function buildChatWidget(app, notebookTracker, renderMimeRegistry, contextManager, streamlitPreviewManager, documentManager) {
3415
3507
  // Get the operating system here so we don't have to do it each time the chat changes.
3416
3508
  // The operating system won't change, duh.
3417
3509
  const operatingSystem = (0,_utils_user__WEBPACK_IMPORTED_MODULE_7__.getOperatingSystem)();
@@ -3421,7 +3513,8 @@ function buildChatWidget(app, notebookTracker, renderMimeRegistry, contextManage
3421
3513
  renderMimeRegistry,
3422
3514
  contextManager,
3423
3515
  streamlitPreviewManager: streamlitPreviewManager,
3424
- operatingSystem
3516
+ operatingSystem,
3517
+ documentManager
3425
3518
  });
3426
3519
  chatWidget.id = 'mito_ai';
3427
3520
  return chatWidget;
@@ -3760,6 +3853,50 @@ UsageBadge.displayName = 'UsageBadge';
3760
3853
  /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (UsageBadge);
3761
3854
 
3762
3855
 
3856
+ /***/ }),
3857
+
3858
+ /***/ "./lib/Extensions/AiChat/cellUpdateUtils.js":
3859
+ /*!**************************************************!*\
3860
+ !*** ./lib/Extensions/AiChat/cellUpdateUtils.js ***!
3861
+ \**************************************************/
3862
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
3863
+
3864
+ __webpack_require__.r(__webpack_exports__);
3865
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
3866
+ /* harmony export */ getCellIdFromCellUpdate: () => (/* binding */ getCellIdFromCellUpdate)
3867
+ /* harmony export */ });
3868
+ /* harmony import */ var _utils_notebook__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../utils/notebook */ "./lib/utils/notebook.js");
3869
+ /*
3870
+ * Copyright (c) Saga Inc.
3871
+ * Distributed under the terms of the GNU Affero General Public License v3.0 License.
3872
+ */
3873
+
3874
+ const getCellIdFromCellUpdate = (cellUpdate, notebookTracker) => {
3875
+ if (!cellUpdate) {
3876
+ return undefined;
3877
+ }
3878
+ if (cellUpdate.type === 'modification') {
3879
+ return cellUpdate.id;
3880
+ }
3881
+ // For 'new' type, find the cell that was inserted after after_cell_id
3882
+ const notebookPanel = notebookTracker.currentWidget;
3883
+ if (!notebookPanel) {
3884
+ return undefined;
3885
+ }
3886
+ if (cellUpdate.after_cell_id === 'new cell') {
3887
+ // New cell was inserted at the top, so it's at index 0
3888
+ return (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_0__.getCellIDByIndexInNotebookPanel)(notebookPanel, 0);
3889
+ }
3890
+ // Get the index of the cell we inserted after, then get the next cell's ID
3891
+ const afterCellIndex = (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_0__.getCellIndexByIDInNotebookPanel)(notebookPanel, cellUpdate.after_cell_id);
3892
+ if (afterCellIndex === undefined) {
3893
+ return undefined;
3894
+ }
3895
+ // The new cell is at index afterCellIndex + 1
3896
+ return (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_0__.getCellIDByIndexInNotebookPanel)(notebookPanel, afterCellIndex + 1);
3897
+ };
3898
+
3899
+
3763
3900
  /***/ }),
3764
3901
 
3765
3902
  /***/ "./lib/Extensions/AiChat/components/AgentReviewPanel.js":
@@ -3814,12 +3951,13 @@ __webpack_require__.r(__webpack_exports__);
3814
3951
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
3815
3952
  /* harmony import */ var _lumino_coreutils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @lumino/coreutils */ "webpack/sharing/consume/default/@lumino/coreutils");
3816
3953
  /* harmony import */ var _lumino_coreutils__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_lumino_coreutils__WEBPACK_IMPORTED_MODULE_1__);
3817
- /* harmony import */ var _utils_checkpoint__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../../utils/checkpoint */ "./lib/utils/checkpoint.js");
3818
- /* harmony import */ var _utils_agentActions__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../../utils/agentActions */ "./lib/utils/agentActions.js");
3819
- /* harmony import */ var _utils_blacklistedWords__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../../utils/blacklistedWords */ "./lib/utils/blacklistedWords.js");
3954
+ /* harmony import */ var _utils_checkpoint__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../../utils/checkpoint */ "./lib/utils/checkpoint.js");
3955
+ /* harmony import */ var _utils_agentActions__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../../utils/agentActions */ "./lib/utils/agentActions.js");
3956
+ /* harmony import */ var _utils_blacklistedWords__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../../utils/blacklistedWords */ "./lib/utils/blacklistedWords.js");
3820
3957
  /* harmony import */ var _utils_sound__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../utils/sound */ "./lib/utils/sound.js");
3821
- /* harmony import */ var _utils_strings__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../../utils/strings */ "./lib/utils/strings.js");
3822
- /* harmony import */ var _utils_notebook__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../utils/notebook */ "./lib/utils/notebook.js");
3958
+ /* harmony import */ var _utils_strings__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../../utils/strings */ "./lib/utils/strings.js");
3959
+ /* harmony import */ var _utils_notebook__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../../utils/notebook */ "./lib/utils/notebook.js");
3960
+ /* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../utils */ "./lib/Extensions/AiChat/utils.js");
3823
3961
  /*
3824
3962
  * Copyright (c) Saga Inc.
3825
3963
  * Distributed under the terms of the GNU Affero General Public License v3.0 License.
@@ -3832,8 +3970,9 @@ __webpack_require__.r(__webpack_exports__);
3832
3970
 
3833
3971
 
3834
3972
 
3973
+
3835
3974
  const AGENT_EXECUTION_DEPTH_LIMIT = 20;
3836
- const useAgentExecution = ({ notebookTracker, app, streamlitPreviewManager, websocketClient, chatHistoryManagerRef, activeThreadIdRef, activeRequestControllerRef, setLoadingStatus, setAutoScrollFollowMode, setHasCheckpoint, addAIMessageFromResponseAndUpdateState, getDuplicateChatHistoryManager, sendAgentExecutionMessage, sendAgentSmartDebugMessage, agentReview, agentTargetNotebookPanelRef, audioContextRef, }) => {
3975
+ const useAgentExecution = ({ notebookTracker, app, streamlitPreviewManager, websocketClient, documentManager, chatHistoryManagerRef, activeThreadIdRef, activeRequestControllerRef, setLoadingStatus, setAutoScrollFollowMode, setHasCheckpoint, addAIMessageFromResponseAndUpdateState, getDuplicateChatHistoryManager, sendAgentExecutionMessage, sendAgentSmartDebugMessage, agentReview, agentTargetNotebookPanelRef, audioContextRef, }) => {
3837
3976
  // Agent execution state
3838
3977
  const [agentExecutionStatus, setAgentExecutionStatus] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)('idle');
3839
3978
  const shouldContinueAgentExecution = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(true);
@@ -3866,10 +4005,12 @@ const useAgentExecution = ({ notebookTracker, app, streamlitPreviewManager, webs
3866
4005
  (0,_utils_sound__WEBPACK_IMPORTED_MODULE_2__.playCompletionSound)(audioContextRef.current);
3867
4006
  };
3868
4007
  const startAgentExecution = async (input, setAgentReviewStatus, messageIndex, additionalContext) => {
3869
- agentTargetNotebookPanelRef.current = notebookTracker.currentWidget;
4008
+ // Ensure a notebook exists before proceeding with agent execution
4009
+ const agentTargetNotebookPanel = await (0,_utils__WEBPACK_IMPORTED_MODULE_3__.ensureNotebookExists)(notebookTracker, documentManager);
4010
+ agentTargetNotebookPanelRef.current = agentTargetNotebookPanel;
3870
4011
  agentReview.acceptAllAICode();
3871
- agentReview.setNotebookSnapshotPreAgentExecution((0,_utils_notebook__WEBPACK_IMPORTED_MODULE_3__.getAIOptimizedCellsInNotebookPanel)(agentTargetNotebookPanelRef.current));
3872
- await (0,_utils_checkpoint__WEBPACK_IMPORTED_MODULE_4__.createCheckpoint)(app, setHasCheckpoint);
4012
+ agentReview.setNotebookSnapshotPreAgentExecution((0,_utils_notebook__WEBPACK_IMPORTED_MODULE_4__.getAIOptimizedCellsInNotebookPanel)(agentTargetNotebookPanelRef.current));
4013
+ await (0,_utils_checkpoint__WEBPACK_IMPORTED_MODULE_5__.createCheckpoint)(app, setHasCheckpoint);
3873
4014
  setAgentExecutionStatus('working');
3874
4015
  setAgentReviewStatus('pre-agent-code-review');
3875
4016
  // Enable follow mode when user starts agent execution
@@ -3910,9 +4051,9 @@ const useAgentExecution = ({ notebookTracker, app, streamlitPreviewManager, webs
3910
4051
  const aiDisplayOptimizedChatItem = chatHistoryManagerRef.current.getLastAIDisplayOptimizedChatItem();
3911
4052
  // # TODO: Make this is a helper function so we can also use it in the auto error fixup!
3912
4053
  if (aiDisplayOptimizedChatItem) {
3913
- const aiGeneratedCode = (0,_utils_strings__WEBPACK_IMPORTED_MODULE_5__.getCodeBlockFromMessage)(aiDisplayOptimizedChatItem.message);
4054
+ const aiGeneratedCode = (0,_utils_strings__WEBPACK_IMPORTED_MODULE_6__.getCodeBlockFromMessage)(aiDisplayOptimizedChatItem.message);
3914
4055
  if (aiGeneratedCode) {
3915
- const securityCheck = (0,_utils_blacklistedWords__WEBPACK_IMPORTED_MODULE_6__.checkForBlacklistedWords)(aiGeneratedCode);
4056
+ const securityCheck = (0,_utils_blacklistedWords__WEBPACK_IMPORTED_MODULE_7__.checkForBlacklistedWords)(aiGeneratedCode);
3916
4057
  if (!securityCheck.safe) {
3917
4058
  console.error('Security Warning:', securityCheck.reason);
3918
4059
  addAIMessageFromResponseAndUpdateState(`I cannot execute this code without your approval because this code did not pass my security checks. ${securityCheck.reason}. For your safety, I am stopping execution of this plan.`, 'agent:execution', chatHistoryManagerRef.current);
@@ -3956,12 +4097,12 @@ const useAgentExecution = ({ notebookTracker, app, streamlitPreviewManager, webs
3956
4097
  // Run the code and handle any errors
3957
4098
  setLoadingStatus('running-code');
3958
4099
  try {
3959
- await (0,_utils_agentActions__WEBPACK_IMPORTED_MODULE_7__.acceptAndRunCellUpdate)(agentResponse.cell_update, agentTargetNotebookPanelRef.current);
4100
+ await (0,_utils_agentActions__WEBPACK_IMPORTED_MODULE_8__.acceptAndRunCellUpdate)(agentResponse.cell_update, agentTargetNotebookPanelRef.current);
3960
4101
  }
3961
4102
  finally {
3962
4103
  setLoadingStatus(undefined);
3963
4104
  }
3964
- const status = await (0,_utils_agentActions__WEBPACK_IMPORTED_MODULE_7__.retryIfExecutionError)(agentTargetNotebookPanelRef.current, app, sendAgentSmartDebugMessage, shouldContinueAgentExecution, markAgentForStopping, chatHistoryManagerRef, setLoadingStatus);
4105
+ const status = await (0,_utils_agentActions__WEBPACK_IMPORTED_MODULE_8__.retryIfExecutionError)(agentTargetNotebookPanelRef.current, app, sendAgentSmartDebugMessage, shouldContinueAgentExecution, markAgentForStopping, chatHistoryManagerRef, setLoadingStatus);
3965
4106
  if (status === 'interupted') {
3966
4107
  break;
3967
4108
  }
@@ -3984,7 +4125,7 @@ const useAgentExecution = ({ notebookTracker, app, streamlitPreviewManager, webs
3984
4125
  setLoadingStatus('running-code');
3985
4126
  let result;
3986
4127
  try {
3987
- result = await (0,_utils_agentActions__WEBPACK_IMPORTED_MODULE_7__.runAllCells)(app, agentTargetNotebookPanelRef.current);
4128
+ result = await (0,_utils_agentActions__WEBPACK_IMPORTED_MODULE_8__.runAllCells)(app, agentTargetNotebookPanelRef.current);
3988
4129
  }
3989
4130
  finally {
3990
4131
  setLoadingStatus(undefined);
@@ -3992,8 +4133,8 @@ const useAgentExecution = ({ notebookTracker, app, streamlitPreviewManager, webs
3992
4133
  // If run_all_cells resulted in an error, handle it through the error fixup process
3993
4134
  if (!result.success && result.errorMessage && result.errorCellId) {
3994
4135
  // Set the error cell as active so the error retry logic can work with it
3995
- (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_3__.setActiveCellByIDInNotebookPanel)(agentTargetNotebookPanelRef.current, result.errorCellId);
3996
- const status = await (0,_utils_agentActions__WEBPACK_IMPORTED_MODULE_7__.retryIfExecutionError)(agentTargetNotebookPanelRef.current, app, sendAgentSmartDebugMessage, shouldContinueAgentExecution, markAgentForStopping, chatHistoryManagerRef, setLoadingStatus);
4136
+ (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_4__.setActiveCellByIDInNotebookPanel)(agentTargetNotebookPanelRef.current, result.errorCellId);
4137
+ const status = await (0,_utils_agentActions__WEBPACK_IMPORTED_MODULE_8__.retryIfExecutionError)(agentTargetNotebookPanelRef.current, app, sendAgentSmartDebugMessage, shouldContinueAgentExecution, markAgentForStopping, chatHistoryManagerRef, setLoadingStatus);
3997
4138
  if (status === 'interupted') {
3998
4139
  break;
3999
4140
  }
@@ -5098,12 +5239,15 @@ const IChatTracker = new _lumino_coreutils__WEBPACK_IMPORTED_MODULE_0__.Token('m
5098
5239
 
5099
5240
  __webpack_require__.r(__webpack_exports__);
5100
5241
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
5242
+ /* harmony export */ ensureNotebookExists: () => (/* binding */ ensureNotebookExists),
5101
5243
  /* harmony export */ getBase64EncodedCellOutput: () => (/* binding */ getBase64EncodedCellOutput),
5102
5244
  /* harmony export */ getBase64EncodedCellOutputInNotebook: () => (/* binding */ getBase64EncodedCellOutputInNotebook)
5103
5245
  /* harmony export */ });
5104
5246
  /* harmony import */ var _utils_notebook__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../utils/notebook */ "./lib/utils/notebook.js");
5105
5247
  /* harmony import */ var _utils_cellOutput__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../utils/cellOutput */ "./lib/utils/cellOutput.js");
5106
5248
  /* harmony import */ var _restAPI_RestAPI__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../restAPI/RestAPI */ "./lib/restAPI/RestAPI.js");
5249
+ /* harmony import */ var _utils_waitForNotebookReady__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../utils/waitForNotebookReady */ "./lib/utils/waitForNotebookReady.js");
5250
+ /* harmony import */ var _utils_notebookMetadata__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../utils/notebookMetadata */ "./lib/utils/notebookMetadata.js");
5107
5251
  /*
5108
5252
  * Copyright (c) Saga Inc.
5109
5253
  * Distributed under the terms of the GNU Affero General Public License v3.0 License.
@@ -5111,6 +5255,8 @@ __webpack_require__.r(__webpack_exports__);
5111
5255
 
5112
5256
 
5113
5257
 
5258
+
5259
+
5114
5260
  const getBase64EncodedCellOutput = async (notebookTracker, cellID) => {
5115
5261
  const notebookPanel = notebookTracker.currentWidget;
5116
5262
  return getBase64EncodedCellOutputInNotebook(notebookPanel, cellID);
@@ -5132,6 +5278,38 @@ const getBase64EncodedCellOutputInNotebook = async (notebookPanel, cellID) => {
5132
5278
  }
5133
5279
  return undefined;
5134
5280
  };
5281
+ /*
5282
+ Ensure a notebook exists. If no notebook is open, create a new one.
5283
+ Returns the notebook panel.
5284
+ */
5285
+ const ensureNotebookExists = async (notebookTracker, documentManager) => {
5286
+ // Check if a notebook already exists
5287
+ let notebookPanel = notebookTracker.currentWidget;
5288
+ if (notebookPanel !== null) {
5289
+ return notebookPanel;
5290
+ }
5291
+ // No notebook exists, create a new one
5292
+ try {
5293
+ // Create a new notebook model (Contents.IModel has a path property)
5294
+ const model = await documentManager.newUntitled({ type: 'notebook' });
5295
+ // Open the notebook using the path from the model
5296
+ await documentManager.open(model.path);
5297
+ // Wait for the notebook to appear in the tracker and be ready
5298
+ await (0,_utils_waitForNotebookReady__WEBPACK_IMPORTED_MODULE_3__.waitForNotebookReady)(notebookTracker);
5299
+ // Get the notebook panel from the tracker
5300
+ notebookPanel = notebookTracker.currentWidget;
5301
+ if (notebookPanel === null) {
5302
+ throw new Error('Failed to get notebook panel after creation');
5303
+ }
5304
+ // Set the notebook ID if it doesn't exist
5305
+ (0,_utils_notebookMetadata__WEBPACK_IMPORTED_MODULE_4__.setNotebookID)(notebookPanel);
5306
+ return notebookPanel;
5307
+ }
5308
+ catch (error) {
5309
+ console.error('Error creating new notebook:', error);
5310
+ throw error;
5311
+ }
5312
+ };
5135
5313
 
5136
5314
 
5137
5315
  /***/ }),
@@ -7996,6 +8174,11 @@ const plugin = {
7996
8174
  removeButtonsFromAllNotebooks();
7997
8175
  }
7998
8176
  });
8177
+ // Set Mito Light as default theme if user hasn't explicitly chosen a different theme
8178
+ // This runs after registration so the theme is available
8179
+ if (manager.theme === 'JupyterLab Light' || !manager.theme) {
8180
+ void manager.setTheme('Mito Light');
8181
+ }
7999
8182
  },
8000
8183
  autoStart: true
8001
8184
  };
@@ -9890,11 +10073,12 @@ const emptyCellPlaceholder = {
9890
10073
  // so that the keybinding can be properly resolved.
9891
10074
  tracker, extensions) => {
9892
10075
  var _a;
9893
- const keyBindings = app.commands.keyBindings.find(b => b.command === _commands__WEBPACK_IMPORTED_MODULE_4__.COMMAND_MITO_AI_OPEN_CHAT);
9894
- const pythonAdvice = `Start writing python or Press ${_lumino_commands__WEBPACK_IMPORTED_MODULE_2__.CommandRegistry.formatKeystroke((_a = keyBindings === null || keyBindings === void 0 ? void 0 : keyBindings.keys[0]) !== null && _a !== void 0 ? _a : 'Accel E')
10076
+ const openChatKeyBindings = app.commands.keyBindings.find(b => b.command === _commands__WEBPACK_IMPORTED_MODULE_4__.COMMAND_MITO_AI_OPEN_CHAT);
10077
+ const openChatKeystroke = _lumino_commands__WEBPACK_IMPORTED_MODULE_2__.CommandRegistry.formatKeystroke((_a = openChatKeyBindings === null || openChatKeyBindings === void 0 ? void 0 : openChatKeyBindings.keys[0]) !== null && _a !== void 0 ? _a : 'Accel E')
9895
10078
  .split(/[+\s]/)
9896
10079
  .map(s => `<kbd>${s}</kbd>`)
9897
- .join(' + ')} to ask Mito AI to write code for you.`;
10080
+ .join(' + ');
10081
+ const pythonAdvice = `Write Python or Press ${openChatKeystroke} to open Mito AI`;
9898
10082
  extensions.addExtension({
9899
10083
  name: 'mito-ai:empty-editor-advice',
9900
10084
  factory: options => {
@@ -10228,7 +10412,8 @@ __webpack_require__.r(__webpack_exports__);
10228
10412
  /* harmony export */ COMMAND_MITO_AI_SEND_AGENT_MESSAGE: () => (/* binding */ COMMAND_MITO_AI_SEND_AGENT_MESSAGE),
10229
10413
  /* harmony export */ COMMAND_MITO_AI_SEND_DEBUG_ERROR_MESSAGE: () => (/* binding */ COMMAND_MITO_AI_SEND_DEBUG_ERROR_MESSAGE),
10230
10414
  /* harmony export */ COMMAND_MITO_AI_SEND_EXPLAIN_CODE_MESSAGE: () => (/* binding */ COMMAND_MITO_AI_SEND_EXPLAIN_CODE_MESSAGE),
10231
- /* harmony export */ COMMAND_MITO_AI_SEND_MESSAGE: () => (/* binding */ COMMAND_MITO_AI_SEND_MESSAGE)
10415
+ /* harmony export */ COMMAND_MITO_AI_SEND_MESSAGE: () => (/* binding */ COMMAND_MITO_AI_SEND_MESSAGE),
10416
+ /* harmony export */ COMMAND_MITO_AI_START_NEW_CHAT: () => (/* binding */ COMMAND_MITO_AI_START_NEW_CHAT)
10232
10417
  /* harmony export */ });
10233
10418
  /*
10234
10419
  * Copyright (c) Saga Inc.
@@ -10245,6 +10430,7 @@ const COMMAND_MITO_AI_SEND_MESSAGE = `${MITO_AI}:send-message`;
10245
10430
  const COMMAND_MITO_AI_SEND_EXPLAIN_CODE_MESSAGE = `${MITO_AI}:send-explain-code-message`;
10246
10431
  const COMMAND_MITO_AI_SEND_DEBUG_ERROR_MESSAGE = `${MITO_AI}:send-debug-error-message`;
10247
10432
  const COMMAND_MITO_AI_SEND_AGENT_MESSAGE = `${MITO_AI}:send-agent-message`;
10433
+ const COMMAND_MITO_AI_START_NEW_CHAT = `${MITO_AI}:start-new-chat`;
10248
10434
  const COMMAND_MITO_AI_CELL_TOOLBAR_ACCEPT_CODE = `toolbar-button:accept-code`;
10249
10435
  const COMMAND_MITO_AI_CELL_TOOLBAR_REJECT_CODE = `toolbar-button:reject-code`;
10250
10436
  // Beta mode commands
@@ -10409,16 +10595,16 @@ __webpack_require__.r(__webpack_exports__);
10409
10595
  /* harmony export */ });
10410
10596
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "webpack/sharing/consume/default/react");
10411
10597
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
10412
- /* harmony import */ var _utils_classNames__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../utils/classNames */ "./lib/utils/classNames.js");
10413
- /* harmony import */ var _utils_strings__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../utils/strings */ "./lib/utils/strings.js");
10414
- /* harmony import */ var _utils_notebook__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../utils/notebook */ "./lib/utils/notebook.js");
10415
- /* harmony import */ var _Extensions_AiChat_ChatMessage_PythonCode__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../Extensions/AiChat/ChatMessage/PythonCode */ "./lib/Extensions/AiChat/ChatMessage/PythonCode.js");
10416
- /* harmony import */ var _Extensions_AiChat_ChatMessage_AssistantCodeBlock__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../../Extensions/AiChat/ChatMessage/AssistantCodeBlock */ "./lib/Extensions/AiChat/ChatMessage/AssistantCodeBlock.js");
10417
- /* harmony import */ var _icons_AlertIcon__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../icons/AlertIcon */ "./lib/icons/AlertIcon.js");
10418
- /* harmony import */ var _AgentComponentHeader__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./AgentComponentHeader */ "./lib/components/AgentComponents/AgentComponentHeader.js");
10598
+ /* harmony import */ var _utils_classNames__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../utils/classNames */ "./lib/utils/classNames.js");
10599
+ /* harmony import */ var _utils_strings__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../utils/strings */ "./lib/utils/strings.js");
10600
+ /* harmony import */ var _Extensions_AiChat_cellUpdateUtils__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../../Extensions/AiChat/cellUpdateUtils */ "./lib/Extensions/AiChat/cellUpdateUtils.js");
10601
+ /* harmony import */ var _Extensions_AiChat_ChatMessage_PythonCode__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../Extensions/AiChat/ChatMessage/PythonCode */ "./lib/Extensions/AiChat/ChatMessage/PythonCode.js");
10602
+ /* harmony import */ var _Extensions_AiChat_ChatMessage_AssistantCodeBlock__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../Extensions/AiChat/ChatMessage/AssistantCodeBlock */ "./lib/Extensions/AiChat/ChatMessage/AssistantCodeBlock.js");
10603
+ /* harmony import */ var _icons_AlertIcon__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../icons/AlertIcon */ "./lib/icons/AlertIcon.js");
10604
+ /* harmony import */ var _AgentComponentHeader__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./AgentComponentHeader */ "./lib/components/AgentComponents/AgentComponentHeader.js");
10419
10605
  /* harmony import */ var _style_ErrorFixupToolUI_css__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../style/ErrorFixupToolUI.css */ "./style/ErrorFixupToolUI.css");
10420
10606
  /* harmony import */ var _style_AgentComponentHeader_css__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../style/AgentComponentHeader.css */ "./style/AgentComponentHeader.css");
10421
- /* harmony import */ var _RunAllCellsToolUI__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./RunAllCellsToolUI */ "./lib/components/AgentComponents/RunAllCellsToolUI.js");
10607
+ /* harmony import */ var _RunAllCellsToolUI__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./RunAllCellsToolUI */ "./lib/components/AgentComponents/RunAllCellsToolUI.js");
10422
10608
  /*
10423
10609
  * Copyright (c) Saga Inc.
10424
10610
  * Distributed under the terms of the GNU Affero General Public License v3.0 License.
@@ -10434,16 +10620,6 @@ __webpack_require__.r(__webpack_exports__);
10434
10620
 
10435
10621
 
10436
10622
 
10437
- const getCellIdFromCellUpdate = (cellUpdate, notebookTracker) => {
10438
- if (!cellUpdate) {
10439
- return undefined;
10440
- }
10441
- if (cellUpdate.type === 'modification') {
10442
- return cellUpdate.id;
10443
- }
10444
- // For 'new' type, get the cell ID by index
10445
- return (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_3__.getCellIDByIndexInNotebookPanel)(notebookTracker.currentWidget, cellUpdate.index);
10446
- };
10447
10623
  const parsePythonErrorType = (content) => {
10448
10624
  if (!content)
10449
10625
  return 'Error';
@@ -10460,16 +10636,16 @@ const processErrorContent = (content) => {
10460
10636
  };
10461
10637
  const ErrorDetectedBlock = ({ errorMessage, renderMimeRegistry, }) => {
10462
10638
  const [expandedError, setExpandedError] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false);
10463
- const rawErrorContent = (0,_utils_strings__WEBPACK_IMPORTED_MODULE_4__.getContentStringFromMessage)(errorMessage);
10639
+ const rawErrorContent = (0,_utils_strings__WEBPACK_IMPORTED_MODULE_3__.getContentStringFromMessage)(errorMessage);
10464
10640
  const errorContent = processErrorContent(rawErrorContent);
10465
10641
  const errorType = parsePythonErrorType(errorContent);
10466
10642
  const toggleError = () => {
10467
10643
  setExpandedError(!expandedError);
10468
10644
  };
10469
- return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: (0,_utils_classNames__WEBPACK_IMPORTED_MODULE_5__.classNames)('error-fixup-container', { expanded: expandedError }) },
10470
- react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_AgentComponentHeader__WEBPACK_IMPORTED_MODULE_6__["default"], { icon: react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_icons_AlertIcon__WEBPACK_IMPORTED_MODULE_7__["default"], null), text: `${errorType} Detected`, onClick: toggleError, isExpanded: expandedError, displayBorder: false }),
10645
+ return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: (0,_utils_classNames__WEBPACK_IMPORTED_MODULE_4__.classNames)('error-fixup-container', { expanded: expandedError }) },
10646
+ react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_AgentComponentHeader__WEBPACK_IMPORTED_MODULE_5__["default"], { icon: react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_icons_AlertIcon__WEBPACK_IMPORTED_MODULE_6__["default"], null), text: `${errorType} Detected`, onClick: toggleError, isExpanded: expandedError, displayBorder: false }),
10471
10647
  expandedError && errorContent && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: "error-fixup-expanded" },
10472
- react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Extensions_AiChat_ChatMessage_PythonCode__WEBPACK_IMPORTED_MODULE_8__["default"], { code: errorContent, renderMimeRegistry: renderMimeRegistry })))));
10648
+ react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Extensions_AiChat_ChatMessage_PythonCode__WEBPACK_IMPORTED_MODULE_7__["default"], { code: errorContent, renderMimeRegistry: renderMimeRegistry })))));
10473
10649
  };
10474
10650
  const GroupedErrorsAndFixes = ({ messages, renderMimeRegistry, notebookTracker, }) => {
10475
10651
  return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: "error-fixup-root" },
@@ -10482,9 +10658,9 @@ const GroupedErrorsAndFixes = ({ messages, renderMimeRegistry, notebookTracker,
10482
10658
  return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(ErrorDetectedBlock, { key: `error-${index}`, errorMessage: messageItem.message, renderMimeRegistry: renderMimeRegistry }));
10483
10659
  }
10484
10660
  if (((_a = messageItem.agentResponse) === null || _a === void 0 ? void 0 : _a.type) === 'run_all_cells') {
10485
- return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_RunAllCellsToolUI__WEBPACK_IMPORTED_MODULE_9__["default"], { key: `run-all-cells-${index}`, inErrorFixup: true }));
10661
+ return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_RunAllCellsToolUI__WEBPACK_IMPORTED_MODULE_8__["default"], { key: `run-all-cells-${index}`, inErrorFixup: true }));
10486
10662
  }
10487
- return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Extensions_AiChat_ChatMessage_AssistantCodeBlock__WEBPACK_IMPORTED_MODULE_10__["default"], { key: `assistant-${index}`, code: messageItem.message.content, codeSummary: (_d = (_c = (_b = messageItem.agentResponse) === null || _b === void 0 ? void 0 : _b.cell_update) === null || _c === void 0 ? void 0 : _c.code_summary) !== null && _d !== void 0 ? _d : 'Fixing error', isCodeComplete: true, renderMimeRegistry: renderMimeRegistry, previewAICode: () => { }, acceptAICode: () => { }, rejectAICode: () => { }, isLastAiMessage: false, codeReviewStatus: "chatPreview", agentModeEnabled: true, isErrorFixup: true, cellId: getCellIdFromCellUpdate((_e = messageItem.agentResponse) === null || _e === void 0 ? void 0 : _e.cell_update, notebookTracker), notebookPanel: notebookTracker.currentWidget }));
10663
+ return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Extensions_AiChat_ChatMessage_AssistantCodeBlock__WEBPACK_IMPORTED_MODULE_9__["default"], { key: `assistant-${index}`, code: messageItem.message.content, codeSummary: (_d = (_c = (_b = messageItem.agentResponse) === null || _b === void 0 ? void 0 : _b.cell_update) === null || _c === void 0 ? void 0 : _c.code_summary) !== null && _d !== void 0 ? _d : 'Fixing error', isCodeComplete: true, renderMimeRegistry: renderMimeRegistry, previewAICode: () => { }, acceptAICode: () => { }, rejectAICode: () => { }, isLastAiMessage: false, codeReviewStatus: "chatPreview", agentModeEnabled: true, isErrorFixup: true, cellId: (0,_Extensions_AiChat_cellUpdateUtils__WEBPACK_IMPORTED_MODULE_10__.getCellIdFromCellUpdate)((_e = messageItem.agentResponse) === null || _e === void 0 ? void 0 : _e.cell_update, notebookTracker), notebookPanel: notebookTracker.currentWidget }));
10488
10664
  }))));
10489
10665
  };
10490
10666
  /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (GroupedErrorsAndFixes);
@@ -11001,7 +11177,7 @@ const MODEL_MAPPINGS = [
11001
11177
  ];
11002
11178
  const ALL_MODEL_DISPLAY_NAMES = MODEL_MAPPINGS.map(mapping => mapping.displayName);
11003
11179
  // Maximum length for displayed model name before truncating
11004
- const DEFAULT_MODEL = _utils_models__WEBPACK_IMPORTED_MODULE_3__.CLAUDE_SONNET_DISPLAY_NAME;
11180
+ const DEFAULT_MODEL = _utils_models__WEBPACK_IMPORTED_MODULE_3__.CLAUDE_HAIKU_DISPLAY_NAME;
11005
11181
  const ModelSelector = ({ onConfigChange }) => {
11006
11182
  const [selectedModel, setSelectedModel] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(DEFAULT_MODEL);
11007
11183
  const [isOpen, setIsOpen] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false);
@@ -11513,6 +11689,9 @@ const SelectedContextContainer = ({ title, type, onRemove, onClick, notebookTrac
11513
11689
  else if (type === 'cell') {
11514
11690
  icon = react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_icons_CodeIcon__WEBPACK_IMPORTED_MODULE_4__["default"], null);
11515
11691
  }
11692
+ else if (type === 'line_selection') {
11693
+ icon = react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_icons_CodeIcon__WEBPACK_IMPORTED_MODULE_4__["default"], null);
11694
+ }
11516
11695
  const handleClick = () => {
11517
11696
  var _a;
11518
11697
  if (type === 'active_cell') {
@@ -11541,16 +11720,66 @@ const SelectedContextContainer = ({ title, type, onRemove, onClick, notebookTrac
11541
11720
  (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_6__.highlightCodeCell)(notebookTracker, value);
11542
11721
  }, 500);
11543
11722
  }
11723
+ else if (type === 'line_selection' && notebookTracker && value) {
11724
+ // Handle line selection context click - scroll to and highlight selected lines
11725
+ try {
11726
+ const selectionInfo = JSON.parse(value);
11727
+ const currentWidget = notebookTracker.currentWidget;
11728
+ if (currentWidget) {
11729
+ // Scroll to the cell, positioning based on the start line
11730
+ // Lines are stored 0-indexed, matching the citation format
11731
+ (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_6__.scrollToCell)(currentWidget, selectionInfo.cellId, selectionInfo.startLine, 'center');
11732
+ // Highlight the selected lines
11733
+ setTimeout(() => {
11734
+ // Re-check currentWidget inside the callback since it may have changed
11735
+ const widget = notebookTracker.currentWidget;
11736
+ if (widget) {
11737
+ (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_6__.highlightLinesOfCodeInCodeCell)(widget, selectionInfo.cellId, selectionInfo.startLine, selectionInfo.endLine);
11738
+ }
11739
+ }, 500);
11740
+ }
11741
+ }
11742
+ catch (_b) {
11743
+ // Ignore JSON parse errors
11744
+ }
11745
+ }
11544
11746
  else if (onClick) {
11545
11747
  // Call the custom onClick handler for other context types
11546
11748
  onClick();
11547
11749
  }
11548
11750
  };
11549
- return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement("button", { className: "selected-context-container", onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), onClick: handleClick, "data-testid": "selected-context-container" },
11751
+ const getTooltipText = () => {
11752
+ if (type.startsWith('image/')) {
11753
+ return `The AI will be able to view the ${title} image before deciding how to respond`;
11754
+ }
11755
+ else if (type === 'file') {
11756
+ return `The path ${title} will be shared with the AI`;
11757
+ }
11758
+ else if (type === 'notebook') {
11759
+ return "The AI will be able to read all of the code and markdown in your notebook. It is included by default in Agent mode.";
11760
+ }
11761
+ else if (type === 'active_cell') {
11762
+ return "The AI will write its code based on the currently active cell. It is included by default in Chat mode.";
11763
+ }
11764
+ else if (type === 'cell') {
11765
+ return `The AI will be able to see the code in ${title}`;
11766
+ }
11767
+ else if (type === 'variable') {
11768
+ return `The AI will receive a summary of the ${title} variable`;
11769
+ }
11770
+ else if (type === 'rule') {
11771
+ return `The AI will be guided by the ${title} rule`;
11772
+ }
11773
+ else if (type === 'db') {
11774
+ return `The AI will be able to access the ${title} database connection`;
11775
+ }
11776
+ return "This context will be included in your message to help the AI understand what you're working with";
11777
+ };
11778
+ return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement("button", { className: "selected-context-container", onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), onClick: handleClick, "data-testid": "selected-context-container", "data-type": type, title: getTooltipText() },
11550
11779
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: `icon`, onClick: (e) => {
11551
11780
  e.stopPropagation(); // Prevent triggering the button's onClick
11552
11781
  onRemove();
11553
- }, title: isHovered ? "Remove rule" : "Selected rule" }, isHovered && type !== 'active_cell' && type !== 'notebook' ? (react__WEBPACK_IMPORTED_MODULE_0___default().createElement("span", { className: "remove-icon" }, "X")) : (react__WEBPACK_IMPORTED_MODULE_0___default().createElement("span", { className: "icon" }, icon))),
11782
+ }, title: isHovered ? "Remove rule" : "Selected rule" }, isHovered && type !== 'active_cell' && type !== 'notebook' && type !== 'line_selection' ? (react__WEBPACK_IMPORTED_MODULE_0___default().createElement("span", { className: "remove-icon" }, "X")) : (react__WEBPACK_IMPORTED_MODULE_0___default().createElement("span", { className: "icon" }, icon))),
11554
11783
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement("span", { className: "rule-name" }, title)));
11555
11784
  };
11556
11785
  /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SelectedContextContainer);
@@ -11790,6 +12019,125 @@ const useDebouncedFunction = (callback, delay) => {
11790
12019
  };
11791
12020
 
11792
12021
 
12022
+ /***/ }),
12023
+
12024
+ /***/ "./lib/hooks/useLineSelection.js":
12025
+ /*!***************************************!*\
12026
+ !*** ./lib/hooks/useLineSelection.js ***!
12027
+ \***************************************/
12028
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
12029
+
12030
+ __webpack_require__.r(__webpack_exports__);
12031
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
12032
+ /* harmony export */ useLineSelection: () => (/* binding */ useLineSelection)
12033
+ /* harmony export */ });
12034
+ /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "webpack/sharing/consume/default/react");
12035
+ /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
12036
+ /* harmony import */ var _utils_notebook__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../utils/notebook */ "./lib/utils/notebook.js");
12037
+ /* harmony import */ var _useDebouncedFunction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./useDebouncedFunction */ "./lib/hooks/useDebouncedFunction.js");
12038
+ /*
12039
+ * Copyright (c) Saga Inc.
12040
+ * Distributed under the terms of the GNU Affero General Public License v3.0 License.
12041
+ */
12042
+
12043
+
12044
+
12045
+ const NO_SELECTION = {
12046
+ cellId: '',
12047
+ cellNumber: 0,
12048
+ startLine: 0,
12049
+ endLine: 0,
12050
+ selectedCode: '',
12051
+ hasSelection: false
12052
+ };
12053
+ /**
12054
+ * Hook that tracks text selection in the active code cell.
12055
+ * Returns selection info when user has text selected (not just cursor position).
12056
+ *
12057
+ * @param notebookTracker - The notebook tracker to monitor
12058
+ * @param cellOrder - Map of cellId to cellNumber (1-indexed)
12059
+ * @returns LineSelectionInfo with selection details, or hasSelection: false if no selection
12060
+ */
12061
+ const useLineSelection = (notebookTracker, cellOrder) => {
12062
+ const [selection, setSelection] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(NO_SELECTION);
12063
+ // Debounce selection updates to avoid excessive re-renders during text selection
12064
+ // `setSelection` is stable, so this keeps the debounced function stable too.
12065
+ const debouncedSetSelection = (0,_useDebouncedFunction__WEBPACK_IMPORTED_MODULE_1__.useDebouncedFunction)(setSelection, 100);
12066
+ // Get current selection from active cell
12067
+ const checkSelection = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(() => {
12068
+ const activeCell = (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_2__.getActiveCell)(notebookTracker);
12069
+ if (!activeCell || activeCell.model.type !== 'code') {
12070
+ debouncedSetSelection(NO_SELECTION);
12071
+ return;
12072
+ }
12073
+ const cellId = activeCell.model.id;
12074
+ const codeCell = activeCell;
12075
+ const cmEditor = codeCell.editor;
12076
+ const editorView = cmEditor === null || cmEditor === void 0 ? void 0 : cmEditor.editor;
12077
+ if (!editorView) {
12078
+ debouncedSetSelection(NO_SELECTION);
12079
+ return;
12080
+ }
12081
+ const state = editorView.state;
12082
+ const mainSelection = state.selection.main;
12083
+ // Check if there's actual text selected (not just cursor)
12084
+ if (mainSelection.from === mainSelection.to) {
12085
+ debouncedSetSelection(NO_SELECTION);
12086
+ return;
12087
+ }
12088
+ // Get 0-indexed line numbers (matching citation format)
12089
+ // CodeMirror's lineAt().number is 1-indexed, so subtract 1
12090
+ const startLineInfo = state.doc.lineAt(mainSelection.from);
12091
+ const endLineInfo = state.doc.lineAt(mainSelection.to);
12092
+ const startLine = startLineInfo.number - 1;
12093
+ const endLine = endLineInfo.number - 1;
12094
+ const cellNumber = cellOrder.get(cellId) || 0;
12095
+ // Extract the full lines that contain the selection
12096
+ const selectedLines = [];
12097
+ for (let lineNum = startLineInfo.number; lineNum <= endLineInfo.number; lineNum++) {
12098
+ const line = state.doc.line(lineNum);
12099
+ selectedLines.push(line.text);
12100
+ }
12101
+ const selectedCode = selectedLines.join('\n');
12102
+ debouncedSetSelection({
12103
+ cellId,
12104
+ cellNumber,
12105
+ startLine,
12106
+ endLine,
12107
+ selectedCode,
12108
+ hasSelection: true
12109
+ });
12110
+ }, [notebookTracker, cellOrder, debouncedSetSelection]);
12111
+ // Poll for selection changes using document-level events
12112
+ (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {
12113
+ // Check selection on various events that might indicate selection change
12114
+ const handleSelectionChange = () => {
12115
+ checkSelection();
12116
+ };
12117
+ // Listen to selection changes at document level
12118
+ document.addEventListener('selectionchange', handleSelectionChange);
12119
+ // Also listen to mouseup for drag selections
12120
+ document.addEventListener('mouseup', handleSelectionChange);
12121
+ // Listen to keyup for keyboard selections (shift+arrow keys)
12122
+ document.addEventListener('keyup', handleSelectionChange);
12123
+ // Check on active cell change
12124
+ const handleActiveCellChanged = () => {
12125
+ checkSelection();
12126
+ };
12127
+ notebookTracker.activeCellChanged.connect(handleActiveCellChanged);
12128
+ // Initial check
12129
+ checkSelection();
12130
+ return () => {
12131
+ document.removeEventListener('selectionchange', handleSelectionChange);
12132
+ document.removeEventListener('mouseup', handleSelectionChange);
12133
+ document.removeEventListener('keyup', handleSelectionChange);
12134
+ notebookTracker.activeCellChanged.disconnect(handleActiveCellChanged);
12135
+ };
12136
+ }, [notebookTracker, checkSelection]);
12137
+ return selection;
12138
+ };
12139
+
12140
+
11793
12141
  /***/ }),
11794
12142
 
11795
12143
  /***/ "./lib/icons/AcceptIcon.js":
@@ -13058,7 +13406,11 @@ const acceptAndRunCellUpdate = async (cellUpdate, notebookPanel) => {
13058
13406
  // in other notebooks.
13059
13407
  if (cellUpdate.type === 'new') {
13060
13408
  // makes the cell the active cell
13061
- (0,_notebook__WEBPACK_IMPORTED_MODULE_1__.createCodeCellAtIndexAndActivate)(notebookPanel, cellUpdate.index);
13409
+ if (cellUpdate.after_cell_id === undefined || cellUpdate.after_cell_id === null) {
13410
+ console.error('after_cell_id is required for new cell creation');
13411
+ return;
13412
+ }
13413
+ (0,_notebook__WEBPACK_IMPORTED_MODULE_1__.createCodeCellAfterCellIDAndActivate)(notebookPanel, cellUpdate.after_cell_id);
13062
13414
  }
13063
13415
  else {
13064
13416
  (0,_notebook__WEBPACK_IMPORTED_MODULE_1__.setActiveCellByIDInNotebookPanel)(notebookPanel, cellUpdate.id);
@@ -14377,7 +14729,7 @@ const GEMINI_3_PRO_MODEL_NAME = 'gemini-3-pro-preview';
14377
14729
  __webpack_require__.r(__webpack_exports__);
14378
14730
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
14379
14731
  /* harmony export */ applyCellEditorExtension: () => (/* binding */ applyCellEditorExtension),
14380
- /* harmony export */ createCodeCellAtIndexAndActivate: () => (/* binding */ createCodeCellAtIndexAndActivate),
14732
+ /* harmony export */ createCodeCellAfterCellIDAndActivate: () => (/* binding */ createCodeCellAfterCellIDAndActivate),
14381
14733
  /* harmony export */ didCellExecutionError: () => (/* binding */ didCellExecutionError),
14382
14734
  /* harmony export */ getAIOptimizedCells: () => (/* binding */ getAIOptimizedCells),
14383
14735
  /* harmony export */ getAIOptimizedCellsInNotebookPanel: () => (/* binding */ getAIOptimizedCellsInNotebookPanel),
@@ -14538,24 +14890,33 @@ const getAIOptimizedCellsInNotebookPanel = (notebookPanel) => {
14538
14890
  }
14539
14891
  return cells;
14540
14892
  };
14541
- function createCodeCellAtIndexAndActivate(notebookPanel, index) {
14893
+ function createCodeCellAfterCellIDAndActivate(notebookPanel, afterCellID) {
14542
14894
  /*
14543
- Create a new code cell at index and make it the active cell.
14895
+ Create a new code cell after the cell with the given ID and make it the active cell.
14896
+ If afterCellID is 'new cell', insert at the very top of the notebook.
14544
14897
  */
14545
14898
  const notebook = notebookPanel.content;
14546
14899
  if (notebook === undefined) {
14547
14900
  return;
14548
14901
  }
14549
- if (index > 0) {
14550
- notebook.activeCellIndex = index - 1;
14551
- // insertBelow makes the new cell the active cell
14552
- _jupyterlab_notebook__WEBPACK_IMPORTED_MODULE_0__.NotebookActions.insertBelow(notebook);
14553
- }
14554
- else {
14902
+ if (afterCellID === 'new cell') {
14903
+ // Insert at the very top of the notebook
14555
14904
  notebook.activeCellIndex = 0;
14556
14905
  // insertAbove makes the new cell the active cell
14557
14906
  _jupyterlab_notebook__WEBPACK_IMPORTED_MODULE_0__.NotebookActions.insertAbove(notebook);
14558
14907
  }
14908
+ else {
14909
+ // Find the cell by ID and get its index
14910
+ const cellIndex = getCellIndexByIDInNotebookPanel(notebookPanel, afterCellID);
14911
+ if (cellIndex === undefined) {
14912
+ console.error(`Cell with ID ${afterCellID} not found`);
14913
+ return;
14914
+ }
14915
+ // Set the active cell to the cell we want to insert after
14916
+ notebook.activeCellIndex = cellIndex;
14917
+ // insertBelow makes the new cell the active cell
14918
+ _jupyterlab_notebook__WEBPACK_IMPORTED_MODULE_0__.NotebookActions.insertBelow(notebook);
14919
+ }
14559
14920
  }
14560
14921
  const didCellExecutionError = (cell) => {
14561
14922
  var _a;
@@ -20942,7 +21303,7 @@ ___CSS_LOADER_EXPORT___.push([module.id, `/*
20942
21303
  display: flex;
20943
21304
  align-items: center;
20944
21305
  text-align: center;
20945
- background-color: var(--jp-layout-color2);
21306
+ background-color: var(--purple-300);
20946
21307
  border-radius: 3px;
20947
21308
  padding: 4px 8px;
20948
21309
  margin: 2px;
@@ -20952,17 +21313,23 @@ ___CSS_LOADER_EXPORT___.push([module.id, `/*
20952
21313
  max-width: 100%;
20953
21314
  min-width: 0;
20954
21315
 
20955
- border: 1px solid var(--jp-border-color1);
21316
+ border: none;
20956
21317
  cursor: pointer;
20957
21318
  }
20958
21319
 
20959
21320
  .selected-context-container:hover {
20960
- background-color: var(--jp-layout-color3);
21321
+ background-color: var(--purple-400);
21322
+ }
21323
+
21324
+ /* Disable hover effect for notebook and active_cell types since they don't have user actions */
21325
+ .selected-context-container[data-type="notebook"]:hover,
21326
+ .selected-context-container[data-type="active_cell"]:hover {
21327
+ background-color: var(--purple-300);
20961
21328
  }
20962
21329
 
20963
21330
  .selected-context-container .rule-name {
20964
21331
  margin-left: 6px;
20965
- color: var(--jp-content-font-color1);
21332
+ color: var(--purple-700);
20966
21333
  white-space: nowrap;
20967
21334
  overflow: hidden;
20968
21335
  text-overflow: ellipsis;
@@ -20975,8 +21342,8 @@ ___CSS_LOADER_EXPORT___.push([module.id, `/*
20975
21342
  justify-content: center;
20976
21343
  width: 12px;
20977
21344
  max-height: 14px;
20978
- color: var(--jp-content-font-color3);
20979
- }`, "",{"version":3,"sources":["webpack://./style/SelectedContextContainer.css"],"names":[],"mappings":"AAAA;;;EAGE;;AAEF;EACE,aAAa;EACb,eAAe;EACf,mBAAmB;EACnB,QAAQ;EACR,iBAAiB;EACjB,kBAAkB;AACpB;;AAEA,6DAA6D;AAC7D;EACE,WAAW;AACb;;AAEA;EACE,aAAa;EACb,mBAAmB;EACnB,kBAAkB;EAClB,yCAAyC;EACzC,kBAAkB;EAClB,gBAAgB;EAChB,WAAW;;EAEX,eAAe;EACf,YAAY;EACZ,eAAe;EACf,YAAY;;EAEZ,yCAAyC;EACzC,eAAe;AACjB;;AAEA;EACE,yCAAyC;AAC3C;;AAEA;EACE,gBAAgB;EAChB,oCAAoC;EACpC,mBAAmB;EACnB,gBAAgB;EAChB,uBAAuB;EACvB,gBAAgB;AAClB;;AAEA;EACE,aAAa;EACb,sBAAsB;EACtB,uBAAuB;EACvB,WAAW;EACX,gBAAgB;EAChB,oCAAoC;AACtC","sourcesContent":["/*\n * Copyright (c) Saga Inc.\n * Distributed under the terms of the GNU Affero General Public License v3.0 License.\n */\n\n.context-container {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 4px;\n padding: 8px 10px;\n overflow-x: hidden;\n}\n\n/* Consistent spacing for all children of context container */\n.context-container>* {\n margin: 2px;\n}\n\n.selected-context-container {\n display: flex;\n align-items: center;\n text-align: center;\n background-color: var(--jp-layout-color2);\n border-radius: 3px;\n padding: 4px 8px;\n margin: 2px;\n\n font-size: 12px;\n height: 20px;\n max-width: 100%;\n min-width: 0;\n\n border: 1px solid var(--jp-border-color1);\n cursor: pointer;\n}\n\n.selected-context-container:hover {\n background-color: var(--jp-layout-color3);\n}\n\n.selected-context-container .rule-name {\n margin-left: 6px;\n color: var(--jp-content-font-color1);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 200px;\n}\n\n.selected-context-container .icon {\n display: flex;\n flex-direction: column;\n justify-content: center;\n width: 12px;\n max-height: 14px;\n color: var(--jp-content-font-color3);\n}"],"sourceRoot":""}]);
21345
+ color: var(--purple-700);
21346
+ }`, "",{"version":3,"sources":["webpack://./style/SelectedContextContainer.css"],"names":[],"mappings":"AAAA;;;EAGE;;AAEF;EACE,aAAa;EACb,eAAe;EACf,mBAAmB;EACnB,QAAQ;EACR,iBAAiB;EACjB,kBAAkB;AACpB;;AAEA,6DAA6D;AAC7D;EACE,WAAW;AACb;;AAEA;EACE,aAAa;EACb,mBAAmB;EACnB,kBAAkB;EAClB,mCAAmC;EACnC,kBAAkB;EAClB,gBAAgB;EAChB,WAAW;;EAEX,eAAe;EACf,YAAY;EACZ,eAAe;EACf,YAAY;;EAEZ,YAAY;EACZ,eAAe;AACjB;;AAEA;EACE,mCAAmC;AACrC;;AAEA,+FAA+F;AAC/F;;EAEE,mCAAmC;AACrC;;AAEA;EACE,gBAAgB;EAChB,wBAAwB;EACxB,mBAAmB;EACnB,gBAAgB;EAChB,uBAAuB;EACvB,gBAAgB;AAClB;;AAEA;EACE,aAAa;EACb,sBAAsB;EACtB,uBAAuB;EACvB,WAAW;EACX,gBAAgB;EAChB,wBAAwB;AAC1B","sourcesContent":["/*\n * Copyright (c) Saga Inc.\n * Distributed under the terms of the GNU Affero General Public License v3.0 License.\n */\n\n.context-container {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 4px;\n padding: 8px 10px;\n overflow-x: hidden;\n}\n\n/* Consistent spacing for all children of context container */\n.context-container>* {\n margin: 2px;\n}\n\n.selected-context-container {\n display: flex;\n align-items: center;\n text-align: center;\n background-color: var(--purple-300);\n border-radius: 3px;\n padding: 4px 8px;\n margin: 2px;\n\n font-size: 12px;\n height: 20px;\n max-width: 100%;\n min-width: 0;\n\n border: none;\n cursor: pointer;\n}\n\n.selected-context-container:hover {\n background-color: var(--purple-400);\n}\n\n/* Disable hover effect for notebook and active_cell types since they don't have user actions */\n.selected-context-container[data-type=\"notebook\"]:hover,\n.selected-context-container[data-type=\"active_cell\"]:hover {\n background-color: var(--purple-300);\n}\n\n.selected-context-container .rule-name {\n margin-left: 6px;\n color: var(--purple-700);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 200px;\n}\n\n.selected-context-container .icon {\n display: flex;\n flex-direction: column;\n justify-content: center;\n width: 12px;\n max-height: 14px;\n color: var(--purple-700);\n}"],"sourceRoot":""}]);
20980
21347
  // Exports
20981
21348
  /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);
20982
21349
 
@@ -24213,4 +24580,4 @@ var update = _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js
24213
24580
  /***/ })
24214
24581
 
24215
24582
  }]);
24216
- //# sourceMappingURL=lib_index_js.49c79c62671528877c61.js.map
24583
+ //# sourceMappingURL=lib_index_js.dfd7975de75d64db80d6.js.map