mito-ai 0.1.43__py3-none-any.whl → 0.1.45__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (62) hide show
  1. mito_ai/__init__.py +3 -3
  2. mito_ai/_version.py +1 -1
  3. mito_ai/anthropic_client.py +2 -3
  4. mito_ai/{app_builder → app_deploy}/__init__.py +1 -1
  5. mito_ai/app_deploy/app_deploy_utils.py +25 -0
  6. mito_ai/{app_builder → app_deploy}/handlers.py +48 -40
  7. mito_ai/{app_builder → app_deploy}/models.py +17 -14
  8. mito_ai/app_manager/handlers.py +33 -0
  9. mito_ai/app_manager/models.py +15 -1
  10. mito_ai/completions/handlers.py +40 -1
  11. mito_ai/completions/models.py +5 -1
  12. mito_ai/completions/prompt_builders/agent_system_message.py +6 -4
  13. mito_ai/completions/prompt_builders/prompt_constants.py +22 -4
  14. mito_ai/completions/providers.py +5 -11
  15. mito_ai/streamlit_conversion/streamlit_agent_handler.py +6 -3
  16. mito_ai/streamlit_conversion/streamlit_utils.py +15 -7
  17. mito_ai/streamlit_conversion/validate_streamlit_app.py +34 -25
  18. mito_ai/streamlit_preview/handlers.py +49 -70
  19. mito_ai/streamlit_preview/utils.py +41 -0
  20. mito_ai/tests/deploy_app/test_app_deploy_utils.py +71 -0
  21. mito_ai/tests/providers/test_anthropic_client.py +2 -2
  22. mito_ai/tests/streamlit_conversion/test_streamlit_agent_handler.py +0 -84
  23. mito_ai/tests/streamlit_conversion/test_validate_streamlit_app.py +0 -15
  24. mito_ai/tests/streamlit_preview/test_streamlit_preview_handler.py +88 -0
  25. mito_ai/tests/streamlit_preview/test_streamlit_preview_manager.py +4 -1
  26. mito_ai/tests/utils/test_anthropic_utils.py +4 -4
  27. mito_ai/utils/anthropic_utils.py +11 -19
  28. mito_ai/utils/telemetry_utils.py +15 -5
  29. {mito_ai-0.1.43.data → mito_ai-0.1.45.data}/data/share/jupyter/labextensions/mito_ai/build_log.json +100 -100
  30. {mito_ai-0.1.43.data → mito_ai-0.1.45.data}/data/share/jupyter/labextensions/mito_ai/package.json +2 -2
  31. {mito_ai-0.1.43.data → mito_ai-0.1.45.data}/data/share/jupyter/labextensions/mito_ai/schemas/mito_ai/package.json.orig +1 -1
  32. {mito_ai-0.1.43.data → mito_ai-0.1.45.data}/data/share/jupyter/labextensions/mito_ai/schemas/mito_ai/toolbar-buttons.json +0 -5
  33. mito_ai-0.1.43.data/data/share/jupyter/labextensions/mito_ai/static/lib_index_js.81703ac2bc645e5c2fc2.js → mito_ai-0.1.45.data/data/share/jupyter/labextensions/mito_ai/static/lib_index_js.0c3368195d954d2ed033.js +1729 -790
  34. mito_ai-0.1.45.data/data/share/jupyter/labextensions/mito_ai/static/lib_index_js.0c3368195d954d2ed033.js.map +1 -0
  35. mito_ai-0.1.43.data/data/share/jupyter/labextensions/mito_ai/static/remoteEntry.502aef26f0416fab7435.js → mito_ai-0.1.45.data/data/share/jupyter/labextensions/mito_ai/static/remoteEntry.684f82575fcc2e3b350c.js +17 -17
  36. mito_ai-0.1.43.data/data/share/jupyter/labextensions/mito_ai/static/remoteEntry.502aef26f0416fab7435.js.map → mito_ai-0.1.45.data/data/share/jupyter/labextensions/mito_ai/static/remoteEntry.684f82575fcc2e3b350c.js.map +1 -1
  37. {mito_ai-0.1.43.dist-info → mito_ai-0.1.45.dist-info}/METADATA +2 -2
  38. {mito_ai-0.1.43.dist-info → mito_ai-0.1.45.dist-info}/RECORD +61 -57
  39. mito_ai-0.1.43.data/data/share/jupyter/labextensions/mito_ai/static/lib_index_js.81703ac2bc645e5c2fc2.js.map +0 -1
  40. {mito_ai-0.1.43.data → mito_ai-0.1.45.data}/data/etc/jupyter/jupyter_server_config.d/mito_ai.json +0 -0
  41. {mito_ai-0.1.43.data → mito_ai-0.1.45.data}/data/share/jupyter/labextensions/mito_ai/static/node_modules_process_browser_js.4b128e94d31a81ebd209.js +0 -0
  42. {mito_ai-0.1.43.data → mito_ai-0.1.45.data}/data/share/jupyter/labextensions/mito_ai/static/node_modules_process_browser_js.4b128e94d31a81ebd209.js.map +0 -0
  43. {mito_ai-0.1.43.data → mito_ai-0.1.45.data}/data/share/jupyter/labextensions/mito_ai/static/style.js +0 -0
  44. {mito_ai-0.1.43.data → mito_ai-0.1.45.data}/data/share/jupyter/labextensions/mito_ai/static/style_index_js.5876024bb17dbd6a3ee6.js +0 -0
  45. {mito_ai-0.1.43.data → mito_ai-0.1.45.data}/data/share/jupyter/labextensions/mito_ai/static/style_index_js.5876024bb17dbd6a3ee6.js.map +0 -0
  46. {mito_ai-0.1.43.data → mito_ai-0.1.45.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
  47. {mito_ai-0.1.43.data → mito_ai-0.1.45.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
  48. {mito_ai-0.1.43.data → mito_ai-0.1.45.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
  49. {mito_ai-0.1.43.data → mito_ai-0.1.45.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
  50. {mito_ai-0.1.43.data → mito_ai-0.1.45.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_dist_esm_index_mjs.6bac1a8c4cc93f15f6b7.js +0 -0
  51. {mito_ai-0.1.43.data → mito_ai-0.1.45.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_dist_esm_index_mjs.6bac1a8c4cc93f15f6b7.js.map +0 -0
  52. {mito_ai-0.1.43.data → mito_ai-0.1.45.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_ui-react_dist_esm_index_mjs.4fcecd65bef9e9847609.js +0 -0
  53. {mito_ai-0.1.43.data → mito_ai-0.1.45.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_ui-react_dist_esm_index_mjs.4fcecd65bef9e9847609.js.map +0 -0
  54. {mito_ai-0.1.43.data → mito_ai-0.1.45.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
  55. {mito_ai-0.1.43.data → mito_ai-0.1.45.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
  56. {mito_ai-0.1.43.data → mito_ai-0.1.45.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_semver_index_js.3f6754ac5116d47de76b.js +0 -0
  57. {mito_ai-0.1.43.data → mito_ai-0.1.45.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_semver_index_js.3f6754ac5116d47de76b.js.map +0 -0
  58. {mito_ai-0.1.43.data → mito_ai-0.1.45.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_vscode-diff_dist_index_js.ea55f1f9346638aafbcf.js +0 -0
  59. {mito_ai-0.1.43.data → mito_ai-0.1.45.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_vscode-diff_dist_index_js.ea55f1f9346638aafbcf.js.map +0 -0
  60. {mito_ai-0.1.43.dist-info → mito_ai-0.1.45.dist-info}/WHEEL +0 -0
  61. {mito_ai-0.1.43.dist-info → mito_ai-0.1.45.dist-info}/entry_points.txt +0 -0
  62. {mito_ai-0.1.43.dist-info → mito_ai-0.1.45.dist-info}/licenses/LICENSE +0 -0
@@ -213,9 +213,10 @@ __webpack_require__.r(__webpack_exports__);
213
213
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
214
214
  /* harmony export */ ChatHistoryManager: () => (/* binding */ ChatHistoryManager)
215
215
  /* harmony export */ });
216
- /* harmony import */ var _utils_notebook__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../utils/notebook */ "./lib/utils/notebook.js");
217
- /* harmony import */ var _utils_strings__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../utils/strings */ "./lib/utils/strings.js");
218
- /* harmony import */ var _utils_user__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../utils/user */ "./lib/utils/user.js");
216
+ /* harmony import */ var _utils_notebook__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../utils/notebook */ "./lib/utils/notebook.js");
217
+ /* harmony import */ var _utils_strings__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../utils/strings */ "./lib/utils/strings.js");
218
+ /* harmony import */ var _utils_user__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../utils/user */ "./lib/utils/user.js");
219
+ /* harmony import */ var _validationUtils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./validationUtils */ "./lib/Extensions/AiChat/validationUtils.js");
219
220
  /*
220
221
  * Copyright (c) Saga Inc.
221
222
  * Distributed under the terms of the GNU Affero General Public License v3.0 License.
@@ -223,6 +224,7 @@ __webpack_require__.r(__webpack_exports__);
223
224
 
224
225
 
225
226
 
227
+
226
228
  /*
227
229
  The ChatHistoryManager is responsible for managing the AI chat history.
228
230
 
@@ -271,6 +273,11 @@ class ChatHistoryManager {
271
273
  this._allAssumptions.clear();
272
274
  this.displayOptimizedChatHistory.forEach(item => {
273
275
  var _a;
276
+ // Validate the agent response if it exists
277
+ if (item.agentResponse !== undefined) {
278
+ item.agentResponse = (0,_validationUtils__WEBPACK_IMPORTED_MODULE_0__.validateAndCorrectAgentResponse)(item.agentResponse);
279
+ }
280
+ // Process the assumptions
274
281
  if ((_a = item.agentResponse) === null || _a === void 0 ? void 0 : _a.analysis_assumptions) {
275
282
  item.agentResponse.analysis_assumptions.forEach(assumption => {
276
283
  this._allAssumptions.add(assumption);
@@ -308,12 +315,13 @@ class ChatHistoryManager {
308
315
  });
309
316
  }
310
317
  async addChatInputMessage(input, activeThreadId, messageIndex, additionalContext) {
311
- const activeCellCode = (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_0__.getActiveCellCode)(this.notebookTracker) || '';
312
- const activeCellID = (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_0__.getActiveCellID)(this.notebookTracker) || '';
318
+ const activeCellCode = (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_1__.getActiveCellCode)(this.notebookTracker) || '';
319
+ const activeCellID = (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_1__.getActiveCellID)(this.notebookTracker) || '';
320
+ const activeNotebookContext = this.contextManager.getActiveNotebookContext();
313
321
  const chatMessageMetadata = {
314
322
  promptType: 'chat',
315
- variables: this.contextManager.variables,
316
- files: this.contextManager.files,
323
+ variables: (activeNotebookContext === null || activeNotebookContext === void 0 ? void 0 : activeNotebookContext.variables) || [],
324
+ files: (activeNotebookContext === null || activeNotebookContext === void 0 ? void 0 : activeNotebookContext.files) || [],
317
325
  activeCellCode: activeCellCode,
318
326
  activeCellId: activeCellID,
319
327
  input: input,
@@ -330,16 +338,17 @@ class ChatHistoryManager {
330
338
  });
331
339
  return chatMessageMetadata;
332
340
  }
333
- addAgentExecutionMessage(activeThreadId, input, additionalContext) {
334
- const aiOptimizedCells = (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_0__.getAIOptimizedCells)(this.notebookTracker);
341
+ addAgentExecutionMessage(activeThreadId, notebookPanel, input, additionalContext) {
342
+ const aiOptimizedCells = (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_1__.getAIOptimizedCellsInNotebookPanel)(notebookPanel);
343
+ const notebookContext = this.contextManager.getNotebookContext(notebookPanel.id);
335
344
  const agentExecutionMetadata = {
336
345
  promptType: 'agent:execution',
337
- variables: this.contextManager.variables,
338
- files: this.contextManager.files,
346
+ variables: (notebookContext === null || notebookContext === void 0 ? void 0 : notebookContext.variables) || [],
347
+ files: (notebookContext === null || notebookContext === void 0 ? void 0 : notebookContext.files) || [],
339
348
  aiOptimizedCells: aiOptimizedCells,
340
349
  input: input || '',
341
350
  threadId: activeThreadId,
342
- isChromeBrowser: (0,_utils_user__WEBPACK_IMPORTED_MODULE_1__.isChromeBasedBrowser)(),
351
+ isChromeBrowser: (0,_utils_user__WEBPACK_IMPORTED_MODULE_2__.isChromeBasedBrowser)(),
343
352
  additionalContext: additionalContext
344
353
  };
345
354
  // We use this function in two ways:
@@ -364,16 +373,14 @@ class ChatHistoryManager {
364
373
  });
365
374
  return agentExecutionMetadata;
366
375
  }
367
- dropMessagesStartingAtIndex(index) {
368
- this.displayOptimizedChatHistory.splice(index);
369
- }
370
376
  addSmartDebugMessage(activeThreadId, errorMessage) {
371
- const activeCellID = (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_0__.getActiveCellID)(this.notebookTracker) || '';
372
- const activeCellCode = (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_0__.getCellCodeByID)(this.notebookTracker, activeCellID) || '';
377
+ const activeCellID = (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_1__.getActiveCellID)(this.notebookTracker) || '';
378
+ const activeCellCode = (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_1__.getCellCodeByID)(this.notebookTracker, activeCellID) || '';
379
+ const activeNotebookContext = this.contextManager.getActiveNotebookContext();
373
380
  const smartDebugMetadata = {
374
381
  promptType: 'smartDebug',
375
- variables: this.contextManager.variables,
376
- files: this.contextManager.files,
382
+ variables: (activeNotebookContext === null || activeNotebookContext === void 0 ? void 0 : activeNotebookContext.variables) || [],
383
+ files: (activeNotebookContext === null || activeNotebookContext === void 0 ? void 0 : activeNotebookContext.files) || [],
377
384
  activeCellCode: activeCellCode,
378
385
  activeCellId: activeCellID,
379
386
  errorMessage: errorMessage,
@@ -387,18 +394,19 @@ class ChatHistoryManager {
387
394
  });
388
395
  return smartDebugMetadata;
389
396
  }
390
- addAgentSmartDebugMessage(activeThreadId, errorMessage) {
391
- const activeCellID = (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_0__.getActiveCellID)(this.notebookTracker);
392
- const activeCellCode = (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_0__.getActiveCellCode)(this.notebookTracker);
397
+ addAgentSmartDebugMessage(activeThreadId, errorMessage, notebookPanel) {
398
+ const activeCellID = (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_1__.getActiveCellIDInNotebookPanel)(notebookPanel);
399
+ const activeCellCode = (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_1__.getCellCodeByIDInNotebookPanel)(notebookPanel, activeCellID);
400
+ const notebookContext = this.contextManager.getNotebookContext(notebookPanel.id);
393
401
  const agentSmartDebugMetadata = {
394
402
  promptType: 'agent:autoErrorFixup',
395
- aiOptimizedCells: (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_0__.getAIOptimizedCells)(this.notebookTracker),
396
- variables: this.contextManager.variables,
397
- files: this.contextManager.files,
403
+ aiOptimizedCells: (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_1__.getAIOptimizedCellsInNotebookPanel)(notebookPanel),
404
+ variables: (notebookContext === null || notebookContext === void 0 ? void 0 : notebookContext.variables) || [],
405
+ files: (notebookContext === null || notebookContext === void 0 ? void 0 : notebookContext.files) || [],
398
406
  errorMessage: errorMessage,
399
407
  error_message_producing_code_cell_id: activeCellID || '',
400
408
  threadId: activeThreadId,
401
- isChromeBrowser: (0,_utils_user__WEBPACK_IMPORTED_MODULE_1__.isChromeBasedBrowser)()
409
+ isChromeBrowser: (0,_utils_user__WEBPACK_IMPORTED_MODULE_2__.isChromeBasedBrowser)()
402
410
  };
403
411
  this.displayOptimizedChatHistory.push({
404
412
  message: getDisplayedOptimizedUserMessage(errorMessage, activeCellCode),
@@ -409,11 +417,12 @@ class ChatHistoryManager {
409
417
  return agentSmartDebugMetadata;
410
418
  }
411
419
  addExplainCodeMessage(activeThreadId) {
412
- const activeCellID = (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_0__.getActiveCellID)(this.notebookTracker);
413
- const activeCellCode = (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_0__.getCellCodeByID)(this.notebookTracker, activeCellID);
420
+ const activeCellID = (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_1__.getActiveCellID)(this.notebookTracker);
421
+ const activeCellCode = (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_1__.getCellCodeByID)(this.notebookTracker, activeCellID);
422
+ const activeNotebookContext = this.contextManager.getActiveNotebookContext();
414
423
  const codeExplainMetadata = {
415
424
  promptType: 'codeExplain',
416
- variables: this.contextManager.variables,
425
+ variables: (activeNotebookContext === null || activeNotebookContext === void 0 ? void 0 : activeNotebookContext.variables) || [],
417
426
  activeCellCode,
418
427
  threadId: activeThreadId
419
428
  };
@@ -440,7 +449,7 @@ class ChatHistoryManager {
440
449
  else {
441
450
  type = 'openai message';
442
451
  }
443
- const activeCellID = (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_0__.getActiveCellID)(this.notebookTracker);
452
+ const activeCellID = (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_1__.getActiveCellID)(this.notebookTracker);
444
453
  this.displayOptimizedChatHistory.push({
445
454
  message: aiMessage,
446
455
  type: type,
@@ -467,13 +476,14 @@ class ChatHistoryManager {
467
476
  }
468
477
  addAIMessageFromAgentResponse(agentResponse) {
469
478
  var _a;
479
+ agentResponse = (0,_validationUtils__WEBPACK_IMPORTED_MODULE_0__.validateAndCorrectAgentResponse)(agentResponse);
470
480
  let content = agentResponse.message;
471
481
  if (agentResponse.type === 'cell_update') {
472
482
  // For cell_update messages, we want to display the code the agent wrote along with
473
483
  // the message it sent. For all other agent responses, we ignore all other fields
474
484
  // and just display the message.
475
485
  const code = (_a = agentResponse.cell_update) === null || _a === void 0 ? void 0 : _a.code;
476
- const codeWithMarkdownFormatting = (0,_utils_strings__WEBPACK_IMPORTED_MODULE_2__.addMarkdownCodeFormatting)(code);
486
+ const codeWithMarkdownFormatting = (0,_utils_strings__WEBPACK_IMPORTED_MODULE_3__.addMarkdownCodeFormatting)(code);
477
487
  if (codeWithMarkdownFormatting !== undefined) {
478
488
  content = content + '\n\n' + codeWithMarkdownFormatting;
479
489
  }
@@ -489,6 +499,9 @@ class ChatHistoryManager {
489
499
  agentResponse: this.deduplicateAssumptions(agentResponse)
490
500
  });
491
501
  }
502
+ dropMessagesStartingAtIndex(index) {
503
+ this.displayOptimizedChatHistory.splice(index);
504
+ }
492
505
  }
493
506
  const getDisplayedOptimizedUserMessage = (input, activeCellCode, messageToAgent = false) => {
494
507
  // Don't include the active cell code if it is an agent planning message
@@ -686,7 +699,29 @@ __webpack_require__.r(__webpack_exports__);
686
699
 
687
700
 
688
701
 
689
- const ChatDropdown = ({ options, onSelect, filterText, maxDropdownItems = 10, isDropdownFromButton = false, onFilterChange, onClose, }) => {
702
+ const priortizeByType = (options, maxPerType) => {
703
+ /*
704
+ Makes sure that some of each type are displayed at the top of the dropdown so
705
+ users can easily see what types of options are available to them.
706
+ */
707
+ const typeCounts = {};
708
+ const prioritizedOptions = [];
709
+ const extraOptions = [];
710
+ for (const option of options) {
711
+ const type = option.type;
712
+ const currentCount = typeCounts[type] || 0;
713
+ if (currentCount < maxPerType) {
714
+ prioritizedOptions.push(option);
715
+ typeCounts[type] = currentCount + 1;
716
+ }
717
+ else {
718
+ extraOptions.push(option);
719
+ }
720
+ }
721
+ // Return prioritized options first, then extras at the bottom
722
+ return [...prioritizedOptions, ...extraOptions];
723
+ };
724
+ const ChatDropdown = ({ options, onSelect, filterText, isDropdownFromButton = false, onFilterChange, onClose, }) => {
690
725
  const [selectedIndex, setSelectedIndex] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(0);
691
726
  const [localFilterText, setLocalFilterText] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(filterText);
692
727
  const searchInputRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(null);
@@ -761,7 +796,7 @@ const ChatDropdown = ({ options, onSelect, filterText, maxDropdownItems = 10, is
761
796
  variable: variable
762
797
  })),
763
798
  ];
764
- const filteredOptions = allOptions.filter((option) => {
799
+ let searchFilteredOptions = allOptions.filter((option) => {
765
800
  if (option.type === 'variable') {
766
801
  return option.variable.variable_name.toLowerCase().includes(effectiveFilterText.toLowerCase()) &&
767
802
  option.variable.type !== "<class 'module'>" &&
@@ -777,7 +812,12 @@ const ChatDropdown = ({ options, onSelect, filterText, maxDropdownItems = 10, is
777
812
  else {
778
813
  return option.rule.toLowerCase().includes(effectiveFilterText.toLowerCase());
779
814
  }
780
- }).slice(0, maxDropdownItems);
815
+ });
816
+ // If user is searching (has filter text), show all matches
817
+ // Otherwise, show only 3 of each type by default
818
+ if (effectiveFilterText.trim() === '') {
819
+ searchFilteredOptions = priortizeByType(searchFilteredOptions, 3);
820
+ }
781
821
  (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {
782
822
  setSelectedIndex(0);
783
823
  }, [options, rules, effectiveFilterText]);
@@ -786,18 +826,18 @@ const ChatDropdown = ({ options, onSelect, filterText, maxDropdownItems = 10, is
786
826
  case 'ArrowDown':
787
827
  case 'Down':
788
828
  event.preventDefault();
789
- setSelectedIndex((prev) => prev < filteredOptions.length - 1 ? prev + 1 : 0);
829
+ setSelectedIndex((prev) => prev < searchFilteredOptions.length - 1 ? prev + 1 : 0);
790
830
  break;
791
831
  case 'ArrowUp':
792
832
  case 'Up':
793
833
  event.preventDefault();
794
- setSelectedIndex((prev) => prev > 0 ? prev - 1 : filteredOptions.length - 1);
834
+ setSelectedIndex((prev) => prev > 0 ? prev - 1 : searchFilteredOptions.length - 1);
795
835
  break;
796
836
  case 'Enter':
797
837
  case 'Return':
798
838
  case 'Tab': {
799
839
  event.preventDefault();
800
- const selectedOption = filteredOptions[selectedIndex];
840
+ const selectedOption = searchFilteredOptions[selectedIndex];
801
841
  if (selectedOption !== undefined) {
802
842
  if (selectedOption.type === 'variable') {
803
843
  onSelect(selectedOption);
@@ -813,7 +853,7 @@ const ChatDropdown = ({ options, onSelect, filterText, maxDropdownItems = 10, is
813
853
  (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {
814
854
  document.addEventListener('keydown', handleKeyDown);
815
855
  return () => document.removeEventListener('keydown', handleKeyDown);
816
- }, [filteredOptions, selectedIndex]);
856
+ }, [searchFilteredOptions, selectedIndex]);
817
857
  // Handle click outside to close dropdown
818
858
  (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {
819
859
  const handleClickOutside = (event) => {
@@ -851,8 +891,8 @@ const ChatDropdown = ({ options, onSelect, filterText, maxDropdownItems = 10, is
851
891
  isDropdownFromButton && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: "chat-dropdown-search" },
852
892
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement("input", { ref: searchInputRef, type: "text", placeholder: "Search variables and rules...", value: localFilterText, onChange: handleSearchInputChange, onKeyDown: handleSearchInputKeyDown, className: "chat-dropdown-search-input" }))),
853
893
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement("ul", { className: "chat-dropdown-list", "data-testid": "chat-dropdown-list" },
854
- filteredOptions.length === 0 && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement("li", { className: "chat-dropdown-item", "data-testid": "chat-dropdown-empty-item" }, "No variables found")),
855
- filteredOptions.map((option, index) => {
894
+ searchFilteredOptions.length === 0 && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement("li", { className: "chat-dropdown-item", "data-testid": "chat-dropdown-empty-item" }, "No variables found")),
895
+ searchFilteredOptions.map((option, index) => {
856
896
  switch (option.type) {
857
897
  case 'variable': {
858
898
  const uniqueKey = option.variable.parent_df
@@ -990,7 +1030,6 @@ __webpack_require__.r(__webpack_exports__);
990
1030
  const ChatInput = ({ app, initialContent, placeholder, onSave, onCancel, isEditing, contextManager, notebookTracker, agentModeEnabled = false, agentExecutionStatus = 'idle', }) => {
991
1031
  var _a;
992
1032
  const [input, setInput] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(initialContent);
993
- const [expandedVariables, setExpandedVariables] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)([]);
994
1033
  const textAreaRef = react__WEBPACK_IMPORTED_MODULE_0___default().useRef(null);
995
1034
  const [activeCellID, setActiveCellID] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)((0,_utils_notebook__WEBPACK_IMPORTED_MODULE_3__.getActiveCellID)(notebookTracker));
996
1035
  const activeCellCode = (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_3__.getActiveCellCode)(notebookTracker) || '';
@@ -1042,9 +1081,10 @@ const ChatInput = ({ app, initialContent, placeholder, onSave, onCancel, isEditi
1042
1081
  if (!textarea)
1043
1082
  return;
1044
1083
  textarea.style.minHeight = 'auto';
1084
+ const maxHeight = 350;
1045
1085
  textarea.style.height = !textarea.value || resetHeight
1046
1086
  ? '80px'
1047
- : `${Math.max(80, textarea.scrollHeight)}px`;
1087
+ : `${Math.min(maxHeight, Math.max(80, textarea.scrollHeight))}px`;
1048
1088
  };
1049
1089
  (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {
1050
1090
  adjustHeight();
@@ -1175,22 +1215,22 @@ const ChatInput = ({ app, initialContent, placeholder, onSave, onCancel, isEditi
1175
1215
  });
1176
1216
  return result;
1177
1217
  };
1178
- // Update the expandedVariables arr when the variable manager changes
1179
- (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {
1218
+ const getExpandedVarialbes = () => {
1219
+ const activeNotebookContext = contextManager === null || contextManager === void 0 ? void 0 : contextManager.getActiveNotebookContext();
1180
1220
  const expandedVariables = [
1181
1221
  // Add base variables (excluding DataFrames)
1182
- ...((contextManager === null || contextManager === void 0 ? void 0 : contextManager.variables.filter(variable => variable.type !== "pd.DataFrame")) || []),
1222
+ ...((activeNotebookContext === null || activeNotebookContext === void 0 ? void 0 : activeNotebookContext.variables.filter(variable => variable.type !== "pd.DataFrame")) || []),
1183
1223
  // Add DataFrames
1184
- ...((contextManager === null || contextManager === void 0 ? void 0 : contextManager.variables.filter((variable) => variable.type === "pd.DataFrame")) || []),
1224
+ ...((activeNotebookContext === null || activeNotebookContext === void 0 ? void 0 : activeNotebookContext.variables.filter((variable) => variable.type === "pd.DataFrame")) || []),
1185
1225
  // Add series with parent DataFrame references
1186
- ...((contextManager === null || contextManager === void 0 ? void 0 : contextManager.variables.filter((variable) => variable.type === "pd.DataFrame").flatMap((df) => Object.entries(df.value).map(([seriesName, _]) => ({
1226
+ ...((activeNotebookContext === null || activeNotebookContext === void 0 ? void 0 : activeNotebookContext.variables.filter((variable) => variable.type === "pd.DataFrame").flatMap((df) => Object.entries(df.value).map(([seriesName, _]) => ({
1187
1227
  variable_name: seriesName,
1188
1228
  type: "col",
1189
1229
  value: "replace_me",
1190
1230
  parent_df: df.variable_name,
1191
1231
  })))) || []),
1192
1232
  // Add files
1193
- ...((contextManager === null || contextManager === void 0 ? void 0 : contextManager.files.map(file => {
1233
+ ...((activeNotebookContext === null || activeNotebookContext === void 0 ? void 0 : activeNotebookContext.files.map(file => {
1194
1234
  var _a;
1195
1235
  return ({
1196
1236
  variable_name: file.file_name,
@@ -1200,8 +1240,8 @@ const ChatInput = ({ app, initialContent, placeholder, onSave, onCancel, isEditi
1200
1240
  });
1201
1241
  })) || [])
1202
1242
  ];
1203
- setExpandedVariables(expandedVariables);
1204
- }, [contextManager === null || contextManager === void 0 ? void 0 : contextManager.variables, contextManager === null || contextManager === void 0 ? void 0 : contextManager.files]);
1243
+ return expandedVariables;
1244
+ };
1205
1245
  // Automatically add active cell context when in Chat mode and there's active cell code
1206
1246
  (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {
1207
1247
  if (!agentModeEnabled) {
@@ -1223,7 +1263,7 @@ const ChatInput = ({ app, initialContent, placeholder, onSave, onCancel, isEditi
1223
1263
  }
1224
1264
  }
1225
1265
  }, [agentModeEnabled, additionalContext, activeCellCode]);
1226
- return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: (0,_utils_classNames__WEBPACK_IMPORTED_MODULE_5__.classNames)("chat-input-container") },
1266
+ return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: (0,_utils_classNames__WEBPACK_IMPORTED_MODULE_5__.classNames)("chat-input-container", { "editing": isEditing }) },
1227
1267
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: 'context-container' },
1228
1268
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_DatabaseButton__WEBPACK_IMPORTED_MODULE_6__["default"], { app: app }),
1229
1269
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_AttachFileButton__WEBPACK_IMPORTED_MODULE_7__["default"], { onFileUploaded: handleFileUpload, notebookTracker: notebookTracker }),
@@ -1263,7 +1303,7 @@ const ChatInput = ({ app, initialContent, placeholder, onSave, onCancel, isEditi
1263
1303
  }
1264
1304
  }
1265
1305
  } }),
1266
- isDropdownVisible && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_ChatDropdown__WEBPACK_IMPORTED_MODULE_9__["default"], { options: expandedVariables, onSelect: handleOptionSelect, filterText: dropdownFilter, isDropdownFromButton: isDropdownFromButton, onFilterChange: setDropdownFilter, onClose: handleDropdownClose }))),
1306
+ isDropdownVisible && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_ChatDropdown__WEBPACK_IMPORTED_MODULE_9__["default"], { options: getExpandedVarialbes(), onSelect: handleOptionSelect, filterText: dropdownFilter, isDropdownFromButton: isDropdownFromButton, onFilterChange: setDropdownFilter, onClose: handleDropdownClose }))),
1267
1307
  isEditing &&
1268
1308
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: "message-edit-buttons" },
1269
1309
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement("button", { onClick: () => onSave(input, undefined, mapAdditionalContext()) }, "Save"),
@@ -1383,11 +1423,11 @@ const ChatMessage = ({ app, message, promptType, agentResponse, messageIndex, mi
1383
1423
  if (messagePart.length > 14) {
1384
1424
  return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null,
1385
1425
  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 })),
1386
- isLastAiMessage && isCodeComplete && codeReviewStatus === 'chatPreview' &&
1426
+ !agentModeEnabled && isLastAiMessage && isCodeComplete && codeReviewStatus === 'chatPreview' &&
1387
1427
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: 'chat-message-buttons' },
1388
1428
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_TextAndIconButton__WEBPACK_IMPORTED_MODULE_9__["default"], { onClick: () => { previewAICode(); }, text: 'Overwrite Active Cell', icon: _icons_PlayButtonIcon__WEBPACK_IMPORTED_MODULE_10__["default"], title: 'Write the Ai generated code to the active cell in the jupyter notebook, replacing the current code.', variant: 'gray', width: 'fit-contents' }),
1389
1429
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_TextAndIconButton__WEBPACK_IMPORTED_MODULE_9__["default"], { onClick: () => { void (0,_utils_copyToClipboard__WEBPACK_IMPORTED_MODULE_11__["default"])(messagePart); }, text: 'Copy', icon: _icons_CopyIcon__WEBPACK_IMPORTED_MODULE_12__["default"], title: 'Copy the Ai generated code to your clipboard', variant: 'gray', width: 'fit-contents' })),
1390
- isLastAiMessage && isCodeComplete && codeReviewStatus === 'codeCellPreview' &&
1430
+ !agentModeEnabled && isLastAiMessage && isCodeComplete && codeReviewStatus === 'codeCellPreview' &&
1391
1431
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: 'chat-message-buttons' },
1392
1432
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_TextButton__WEBPACK_IMPORTED_MODULE_13__["default"], { onClick: () => { acceptAICode(); }, text: `Accept code ${operatingSystem === 'mac' ? '⌘Y' : 'Ctrl+Y'}`, title: 'Accept the Ai generated code', variant: 'green', width: 'fit-contents' }),
1393
1433
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_TextButton__WEBPACK_IMPORTED_MODULE_13__["default"], { onClick: () => { rejectAICode(); }, text: `Reject code ${operatingSystem === 'mac' ? '⌘U' : 'Ctrl+U'}`, title: 'Reject the Ai generated code and revert to the previous version of the code cell', variant: 'red', width: 'fit-contents' })),
@@ -1468,7 +1508,7 @@ const Citation = ({ citationIndex, cellId, line, notebookTracker }) => {
1468
1508
  // we set the end line to the start line if only a single line number is provided.
1469
1509
  const lineEnd = typeof line === 'number' ? line : line.end;
1470
1510
  // Scroll to the cell and highlight the lines
1471
- (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_2__.scrollToAndHighlightCell)(notebookTracker, cellId, lineStart, lineEnd);
1511
+ (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_2__.scrollToAndHighlightCell)(notebookTracker.currentWidget, cellId, lineStart, lineEnd);
1472
1512
  };
1473
1513
  return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement("span", { className: "citation-button", onClick: handleClick, title: getLineDisplayText(line) }, citationIndex));
1474
1514
  };
@@ -1958,42 +1998,43 @@ __webpack_require__.r(__webpack_exports__);
1958
1998
  /* harmony import */ var _jupyterlab_ui_components__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_jupyterlab_ui_components__WEBPACK_IMPORTED_MODULE_2__);
1959
1999
  /* harmony import */ var _lumino_coreutils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @lumino/coreutils */ "webpack/sharing/consume/default/@lumino/coreutils");
1960
2000
  /* harmony import */ var _lumino_coreutils__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_lumino_coreutils__WEBPACK_IMPORTED_MODULE_3__);
1961
- /* harmony import */ var _commands__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ../../commands */ "./lib/commands.js");
1962
- /* harmony import */ var _components_AgentComponents_ErrorFixupToolUI__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(/*! ../../components/AgentComponents/ErrorFixupToolUI */ "./lib/components/AgentComponents/ErrorFixupToolUI.js");
1963
- /* harmony import */ var _components_DropdownMenu__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ../../components/DropdownMenu */ "./lib/components/DropdownMenu.js");
1964
- /* harmony import */ var _components_IconButton__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ../../components/IconButton */ "./lib/components/IconButton.js");
1965
- /* harmony import */ var _components_LoadingCircle__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(/*! ../../components/LoadingCircle */ "./lib/components/LoadingCircle.js");
1966
- /* harmony import */ var _components_LoadingDots__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(/*! ../../components/LoadingDots */ "./lib/components/LoadingDots.js");
2001
+ /* harmony import */ var _commands__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ../../commands */ "./lib/commands.js");
2002
+ /* harmony import */ var _components_AgentComponents_ErrorFixupToolUI__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(/*! ../../components/AgentComponents/ErrorFixupToolUI */ "./lib/components/AgentComponents/ErrorFixupToolUI.js");
2003
+ /* harmony import */ var _components_DropdownMenu__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ../../components/DropdownMenu */ "./lib/components/DropdownMenu.js");
2004
+ /* harmony import */ var _components_IconButton__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ../../components/IconButton */ "./lib/components/IconButton.js");
2005
+ /* harmony import */ var _components_LoadingCircle__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(/*! ../../components/LoadingCircle */ "./lib/components/LoadingCircle.js");
1967
2006
  /* harmony import */ var _components_ModelSelector__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../components/ModelSelector */ "./lib/components/ModelSelector.js");
1968
- /* harmony import */ var _components_NextStepsPills__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(/*! ../../components/NextStepsPills */ "./lib/components/NextStepsPills.js");
1969
- /* harmony import */ var _components_TextAndIconButton__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(/*! ../../components/TextAndIconButton */ "./lib/components/TextAndIconButton.js");
1970
- /* harmony import */ var _components_ToggleButton__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(/*! ../../components/ToggleButton */ "./lib/components/ToggleButton.js");
1971
- /* harmony import */ var _icons__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ../../icons */ "./lib/icons/index.js");
1972
- /* harmony import */ var _icons_MitoLogo__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! ../../icons/MitoLogo */ "./lib/icons/MitoLogo.js");
1973
- /* harmony import */ var _icons_UndoIcon__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(/*! ../../icons/UndoIcon */ "./lib/icons/UndoIcon.js");
2007
+ /* harmony import */ var _components_NextStepsPills__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(/*! ../../components/NextStepsPills */ "./lib/components/NextStepsPills.js");
2008
+ /* harmony import */ var _components_TextAndIconButton__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(/*! ../../components/TextAndIconButton */ "./lib/components/TextAndIconButton.js");
2009
+ /* harmony import */ var _components_ToggleButton__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(/*! ../../components/ToggleButton */ "./lib/components/ToggleButton.js");
2010
+ /* harmony import */ var _icons__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! ../../icons */ "./lib/icons/index.js");
2011
+ /* harmony import */ var _icons_MitoLogo__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(/*! ../../icons/MitoLogo */ "./lib/icons/MitoLogo.js");
2012
+ /* harmony import */ var _icons_UndoIcon__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(/*! ../../icons/UndoIcon */ "./lib/icons/UndoIcon.js");
1974
2013
  /* harmony import */ var _utils_agentActions__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ../../utils/agentActions */ "./lib/utils/agentActions.js");
1975
2014
  /* harmony import */ var _utils_blacklistedWords__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ../../utils/blacklistedWords */ "./lib/utils/blacklistedWords.js");
1976
2015
  /* harmony import */ var _utils_checkpoint__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../../utils/checkpoint */ "./lib/utils/checkpoint.js");
1977
- /* harmony import */ var _utils_chatHistory__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ../../utils/chatHistory */ "./lib/utils/chatHistory.js");
1978
- /* harmony import */ var _utils_codeDiff__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ../../utils/codeDiff */ "./lib/utils/codeDiff.js");
1979
- /* harmony import */ var _utils_notebook__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../../utils/notebook */ "./lib/utils/notebook.js");
2016
+ /* harmony import */ var _utils_chatHistory__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ../../utils/chatHistory */ "./lib/utils/chatHistory.js");
2017
+ /* harmony import */ var _utils_codeDiff__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ../../utils/codeDiff */ "./lib/utils/codeDiff.js");
2018
+ /* harmony import */ var _utils_notebook__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ../../utils/notebook */ "./lib/utils/notebook.js");
2019
+ /* harmony import */ var _utils_cellOutput__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../../utils/cellOutput */ "./lib/utils/cellOutput.js");
1980
2020
  /* harmony import */ var _utils_scroll__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../../utils/scroll */ "./lib/utils/scroll.js");
1981
2021
  /* harmony import */ var _utils_strings__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ../../utils/strings */ "./lib/utils/strings.js");
1982
2022
  /* harmony import */ var _utils_waitForNotebookReady__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../../utils/waitForNotebookReady */ "./lib/utils/waitForNotebookReady.js");
1983
2023
  /* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./utils */ "./lib/Extensions/AiChat/utils.js");
1984
- /* harmony import */ var _SettingsManager_SettingsManagerPlugin__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ../SettingsManager/SettingsManagerPlugin */ "./lib/Extensions/SettingsManager/SettingsManagerPlugin.js");
2024
+ /* harmony import */ var _SettingsManager_SettingsManagerPlugin__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ../SettingsManager/SettingsManagerPlugin */ "./lib/Extensions/SettingsManager/SettingsManagerPlugin.js");
1985
2025
  /* harmony import */ var _SettingsManager_profiler_ProfilerPage__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../SettingsManager/profiler/ProfilerPage */ "./lib/Extensions/SettingsManager/profiler/ProfilerPage.js");
1986
- /* harmony import */ var _CTACarousel__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(/*! ./CTACarousel */ "./lib/Extensions/AiChat/CTACarousel.js");
1987
- /* harmony import */ var _CodeDiffDisplay__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ./CodeDiffDisplay */ "./lib/Extensions/AiChat/CodeDiffDisplay.js");
2026
+ /* harmony import */ var _CTACarousel__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(/*! ./CTACarousel */ "./lib/Extensions/AiChat/CTACarousel.js");
2027
+ /* harmony import */ var _CodeDiffDisplay__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ./CodeDiffDisplay */ "./lib/Extensions/AiChat/CodeDiffDisplay.js");
1988
2028
  /* harmony import */ var _FirstMessage__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./FirstMessage */ "./lib/Extensions/AiChat/FirstMessage.js");
1989
- /* harmony import */ var _ChatMessage_ChatInput__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(/*! ./ChatMessage/ChatInput */ "./lib/Extensions/AiChat/ChatMessage/ChatInput.js");
1990
- /* harmony import */ var _ChatMessage_ChatMessage__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(/*! ./ChatMessage/ChatMessage */ "./lib/Extensions/AiChat/ChatMessage/ChatMessage.js");
1991
- /* harmony import */ var _ChatMessage_RevertQuestionnaire__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(/*! ./ChatMessage/RevertQuestionnaire */ "./lib/Extensions/AiChat/ChatMessage/RevertQuestionnaire.js");
1992
- /* harmony import */ var _ChatMessage_ScrollableSuggestions__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(/*! ./ChatMessage/ScrollableSuggestions */ "./lib/Extensions/AiChat/ChatMessage/ScrollableSuggestions.js");
2029
+ /* harmony import */ var _ChatMessage_ChatInput__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(/*! ./ChatMessage/ChatInput */ "./lib/Extensions/AiChat/ChatMessage/ChatInput.js");
2030
+ /* harmony import */ var _ChatMessage_ChatMessage__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(/*! ./ChatMessage/ChatMessage */ "./lib/Extensions/AiChat/ChatMessage/ChatMessage.js");
2031
+ /* harmony import */ var _ChatMessage_RevertQuestionnaire__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(/*! ./ChatMessage/RevertQuestionnaire */ "./lib/Extensions/AiChat/ChatMessage/RevertQuestionnaire.js");
2032
+ /* harmony import */ var _ChatMessage_ScrollableSuggestions__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(/*! ./ChatMessage/ScrollableSuggestions */ "./lib/Extensions/AiChat/ChatMessage/ScrollableSuggestions.js");
1993
2033
  /* harmony import */ var _ChatHistoryManager__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./ChatHistoryManager */ "./lib/Extensions/AiChat/ChatHistoryManager.js");
1994
2034
  /* harmony import */ var _style_button_css__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../../style/button.css */ "./style/button.css");
1995
2035
  /* harmony import */ var _style_ChatTaskpane_css__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../../style/ChatTaskpane.css */ "./style/ChatTaskpane.css");
1996
2036
  /* harmony import */ var _style_TextButton_css__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../../style/TextButton.css */ "./style/TextButton.css");
2037
+ /* harmony import */ var _components_LoadingDots__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(/*! ../../components/LoadingDots */ "./lib/components/LoadingDots.js");
1997
2038
  /*
1998
2039
  * Copyright (c) Saga Inc.
1999
2040
  * Distributed under the terms of the GNU Affero General Public License v3.0 License.
@@ -2015,7 +2056,6 @@ __webpack_require__.r(__webpack_exports__);
2015
2056
 
2016
2057
 
2017
2058
 
2018
-
2019
2059
  // Internal imports - Icons
2020
2060
 
2021
2061
 
@@ -2033,6 +2073,7 @@ __webpack_require__.r(__webpack_exports__);
2033
2073
 
2034
2074
 
2035
2075
 
2076
+
2036
2077
  // Internal imports - Chat components
2037
2078
 
2038
2079
 
@@ -2046,12 +2087,14 @@ __webpack_require__.r(__webpack_exports__);
2046
2087
 
2047
2088
 
2048
2089
 
2090
+
2049
2091
  const AGENT_EXECUTION_DEPTH_LIMIT = 20;
2050
2092
  const getDefaultChatHistoryManager = (notebookTracker, contextManager) => {
2051
2093
  const chatHistoryManager = new _ChatHistoryManager__WEBPACK_IMPORTED_MODULE_7__.ChatHistoryManager(contextManager, notebookTracker);
2052
2094
  return chatHistoryManager;
2053
2095
  };
2054
2096
  const ChatTaskpane = ({ notebookTracker, renderMimeRegistry, contextManager, app, operatingSystem, websocketClient, }) => {
2097
+ var _a;
2055
2098
  const [chatHistoryManager, setChatHistoryManager] = (0,react__WEBPACK_IMPORTED_MODULE_1__.useState)(() => getDefaultChatHistoryManager(notebookTracker, contextManager));
2056
2099
  const chatHistoryManagerRef = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(chatHistoryManager);
2057
2100
  const [loadingAIResponse, setLoadingAIResponse] = (0,react__WEBPACK_IMPORTED_MODULE_1__.useState)(false);
@@ -2097,11 +2140,14 @@ const ChatTaskpane = ({ notebookTracker, renderMimeRegistry, contextManager, app
2097
2140
  3. idle: the agent is idle
2098
2141
  */
2099
2142
  const [agentExecutionStatus, setAgentExecutionStatus] = (0,react__WEBPACK_IMPORTED_MODULE_1__.useState)('idle');
2143
+ const agentTargetNotebookPanelRef = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(null);
2100
2144
  // We use a ref to always access the most up-to-date value during a function's execution. Refs immediately reflect changes,
2101
2145
  // unlike state variables, which are captured at the beginning of a function and may not reflect updates made during execution.
2102
2146
  const shouldContinueAgentExecution = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(true);
2103
2147
  const streamingContentRef = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)('');
2104
2148
  const streamHandlerRef = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(null);
2149
+ // Track active requests for cancellation
2150
+ const activeRequestControllerRef = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(null);
2105
2151
  // State for managing next steps from responses
2106
2152
  // If the user hides the next steps, we keep them hidden until they re-open them
2107
2153
  const [nextSteps, setNextSteps] = (0,react__WEBPACK_IMPORTED_MODULE_1__.useState)([]);
@@ -2381,13 +2427,16 @@ const ChatTaskpane = ({ notebookTracker, renderMimeRegistry, contextManager, app
2381
2427
  await _sendMessageAndSaveResponse(smartDebugCompletionRequest, newChatHistoryManager);
2382
2428
  };
2383
2429
  const sendAgentSmartDebugMessage = async (errorMessage) => {
2430
+ if (agentTargetNotebookPanelRef.current === null) {
2431
+ return;
2432
+ }
2384
2433
  // Step 0: reset the state for a new message
2385
2434
  resetForNewMessage();
2386
2435
  // Enable follow mode when sending agent debug message (same behavior as other modes)
2387
2436
  setAutoScrollFollowMode(true);
2388
2437
  // Step 1: Create message metadata
2389
2438
  const newChatHistoryManager = getDuplicateChatHistoryManager();
2390
- const agentSmartDebugMessage = newChatHistoryManager.addAgentSmartDebugMessage(activeThreadIdRef.current, errorMessage);
2439
+ const agentSmartDebugMessage = newChatHistoryManager.addAgentSmartDebugMessage(activeThreadIdRef.current, errorMessage, agentTargetNotebookPanelRef.current);
2391
2440
  setChatHistoryManager(newChatHistoryManager);
2392
2441
  setLoadingAIResponse(true);
2393
2442
  // Step 2: Send the message to the AI
@@ -2422,17 +2471,21 @@ const ChatTaskpane = ({ notebookTracker, renderMimeRegistry, contextManager, app
2422
2471
  const sendAgentExecutionMessage = async (input, messageIndex, sendCellIDOutput = undefined, additionalContext) => {
2423
2472
  // Step 0: reset the state for a new message
2424
2473
  resetForNewMessage();
2474
+ const agentTargetNotebookPanel = agentTargetNotebookPanelRef.current;
2475
+ if (agentTargetNotebookPanel === null) {
2476
+ return;
2477
+ }
2425
2478
  // Step 1: Add the user's message to the chat history
2426
2479
  const newChatHistoryManager = getDuplicateChatHistoryManager();
2427
2480
  if (messageIndex !== undefined) {
2428
2481
  // Drop all of the messages starting at the message index
2429
2482
  newChatHistoryManager.dropMessagesStartingAtIndex(messageIndex);
2430
2483
  }
2431
- const agentExecutionMetadata = newChatHistoryManager.addAgentExecutionMessage(activeThreadIdRef.current, input, additionalContext);
2484
+ const agentExecutionMetadata = newChatHistoryManager.addAgentExecutionMessage(activeThreadIdRef.current, agentTargetNotebookPanel, input, additionalContext);
2432
2485
  if (messageIndex !== undefined) {
2433
2486
  agentExecutionMetadata.index = messageIndex;
2434
2487
  }
2435
- agentExecutionMetadata.base64EncodedActiveCellOutput = await (0,_utils__WEBPACK_IMPORTED_MODULE_12__.getBase64EncodedCellOutput)(notebookTracker, sendCellIDOutput);
2488
+ agentExecutionMetadata.base64EncodedActiveCellOutput = await (0,_utils__WEBPACK_IMPORTED_MODULE_12__.getBase64EncodedCellOutputInNotebook)(agentTargetNotebookPanel, sendCellIDOutput);
2436
2489
  setChatHistoryManager(newChatHistoryManager);
2437
2490
  setLoadingAIResponse(true);
2438
2491
  // Step 2: Send the message to the AI
@@ -2468,7 +2521,7 @@ const ChatTaskpane = ({ notebookTracker, renderMimeRegistry, contextManager, app
2468
2521
  // Add the active cell output to the metadata afterwards setting the chatHistoryManager so that
2469
2522
  // we don't have to wait on turning the output into a base64 image before we can add the user's message
2470
2523
  // to the chat.
2471
- const activeCellOutput = await (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_13__.getActiveCellOutput)(notebookTracker);
2524
+ const activeCellOutput = await (0,_utils_cellOutput__WEBPACK_IMPORTED_MODULE_13__.getActiveCellOutput)(notebookTracker);
2472
2525
  if (activeCellOutput !== undefined) {
2473
2526
  chatMessageMetadata.base64EncodedActiveCellOutput = activeCellOutput;
2474
2527
  }
@@ -2492,6 +2545,9 @@ const ChatTaskpane = ({ notebookTracker, renderMimeRegistry, contextManager, app
2492
2545
  };
2493
2546
  const _sendMessageAndSaveResponse = async (completionRequest, newChatHistoryManager) => {
2494
2547
  var _a, _b, _c, _d;
2548
+ // Create AbortController for this request
2549
+ const abortController = new AbortController();
2550
+ activeRequestControllerRef.current = abortController;
2495
2551
  // Capture the completion request for debugging
2496
2552
  (0,_SettingsManager_profiler_ProfilerPage__WEBPACK_IMPORTED_MODULE_14__.captureCompletionRequest)(completionRequest);
2497
2553
  if (completionRequest.stream) {
@@ -2560,7 +2616,15 @@ const ChatTaskpane = ({ notebookTracker, renderMimeRegistry, contextManager, app
2560
2616
  // NON-STREAMING RESPONSES
2561
2617
  // Once we move everything to streaming, we can remove everything in this else block
2562
2618
  try {
2619
+ // Check if request was aborted before making the call
2620
+ if (abortController.signal.aborted) {
2621
+ throw new Error('Request aborted');
2622
+ }
2563
2623
  const aiResponse = await websocketClient.sendMessage(completionRequest);
2624
+ // Check if request was aborted after receiving response
2625
+ if (abortController.signal.aborted) {
2626
+ throw new Error('Request aborted');
2627
+ }
2564
2628
  if (aiResponse.error) {
2565
2629
  console.group('Error calling OpenAI API:');
2566
2630
  console.error('Title:', aiResponse.error.title);
@@ -2595,6 +2659,11 @@ const ChatTaskpane = ({ notebookTracker, renderMimeRegistry, contextManager, app
2595
2659
  }
2596
2660
  }
2597
2661
  catch (error) {
2662
+ // Check if this was an abort error
2663
+ if (error.message === 'Request aborted') {
2664
+ // Don't show error message for aborted requests
2665
+ return false;
2666
+ }
2598
2667
  addAIMessageFromResponseAndUpdateState(error.title ? error.title : `${error}`, 'chat', newChatHistoryManager, false);
2599
2668
  addAIMessageFromResponseAndUpdateState(error.hint ? error.hint : `${error}`, completionRequest.metadata.promptType, newChatHistoryManager, true);
2600
2669
  }
@@ -2604,6 +2673,10 @@ const ChatTaskpane = ({ notebookTracker, renderMimeRegistry, contextManager, app
2604
2673
  setLoadingAIResponse(false);
2605
2674
  }
2606
2675
  }
2676
+ // Clean up AbortController
2677
+ if (activeRequestControllerRef.current === abortController) {
2678
+ activeRequestControllerRef.current = null;
2679
+ }
2607
2680
  return true;
2608
2681
  };
2609
2682
  const addAIMessageFromResponseAndUpdateState = (messageContent, promptType, chatHistoryManager, mitoAIConnectionError = false, mitoAIConnectionErrorType = null) => {
@@ -2614,21 +2687,36 @@ const ChatTaskpane = ({ notebookTracker, renderMimeRegistry, contextManager, app
2614
2687
  chatHistoryManager.addAIMessageFromResponse(messageContent, promptType, mitoAIConnectionError, mitoAIConnectionErrorType);
2615
2688
  setChatHistoryManager(chatHistoryManager);
2616
2689
  };
2617
- const markAgentForStopping = () => {
2618
- // Signal that the agent should stop after current task
2619
- shouldContinueAgentExecution.current = false;
2620
- // Update UI to show stopping state
2621
- setAgentExecutionStatus('stopping');
2622
- };
2623
- const finalizeAgentStop = () => {
2624
- // Notify user that agent has been stopped
2690
+ const markAgentForStopping = async (reason = 'naturalConclusion') => {
2691
+ // Signal that the agent should stop immediately
2625
2692
  shouldContinueAgentExecution.current = false;
2626
- const newChatHistoryManager = getDuplicateChatHistoryManager();
2627
- addAIMessageFromResponseAndUpdateState("Agent execution stopped. You can continue the conversation or start a new one.", 'chat', newChatHistoryManager);
2628
- // Reset agent to idle state
2693
+ // Update state/UI
2629
2694
  setAgentExecutionStatus('idle');
2695
+ setLoadingAIResponse(false);
2696
+ if (reason === 'userStop') {
2697
+ // Immediately abort any ongoing requests
2698
+ if (activeRequestControllerRef.current) {
2699
+ activeRequestControllerRef.current.abort();
2700
+ activeRequestControllerRef.current = null;
2701
+ }
2702
+ // Add feedback message based on reason
2703
+ const newChatHistoryManager = getDuplicateChatHistoryManager();
2704
+ addAIMessageFromResponseAndUpdateState("Agent stopped by user.", 'chat', newChatHistoryManager);
2705
+ // Send stop message to backend
2706
+ await websocketClient.sendMessage({
2707
+ type: "stop_agent",
2708
+ message_id: _lumino_coreutils__WEBPACK_IMPORTED_MODULE_3__.UUID.uuid4(),
2709
+ metadata: {
2710
+ promptType: "stop_agent",
2711
+ threadId: activeThreadIdRef.current
2712
+ },
2713
+ stream: false
2714
+ });
2715
+ }
2716
+ return;
2630
2717
  };
2631
2718
  const startAgentExecution = async (input, messageIndex, additionalContext) => {
2719
+ agentTargetNotebookPanelRef.current = notebookTracker.currentWidget;
2632
2720
  await (0,_utils_checkpoint__WEBPACK_IMPORTED_MODULE_15__.createCheckpoint)(app, setHasCheckpoint);
2633
2721
  setAgentExecutionStatus('working');
2634
2722
  // Enable follow mode when user starts agent execution
@@ -2642,7 +2730,7 @@ const ChatTaskpane = ({ notebookTracker, renderMimeRegistry, contextManager, app
2642
2730
  while (!isAgentFinished && agentExecutionDepth <= AGENT_EXECUTION_DEPTH_LIMIT) {
2643
2731
  // Check if we should continue execution
2644
2732
  if (!shouldContinueAgentExecution.current) {
2645
- finalizeAgentStop();
2733
+ await markAgentForStopping();
2646
2734
  break;
2647
2735
  }
2648
2736
  // Only the first message sent to the Agent should contain the user's input.
@@ -2667,31 +2755,40 @@ const ChatTaskpane = ({ notebookTracker, renderMimeRegistry, contextManager, app
2667
2755
  if (!securityCheck.safe) {
2668
2756
  console.error('Security Warning:', securityCheck.reason);
2669
2757
  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', chatHistoryManager);
2670
- finalizeAgentStop();
2758
+ await markAgentForStopping();
2671
2759
  break;
2672
2760
  }
2673
2761
  }
2674
2762
  }
2675
2763
  const agentResponse = aiDisplayOptimizedChatItem === null || aiDisplayOptimizedChatItem === void 0 ? void 0 : aiDisplayOptimizedChatItem.agentResponse;
2764
+ if (agentTargetNotebookPanelRef.current === null) {
2765
+ // If the agent target notebook panel is not set, we don't know where to run the code so we stop
2766
+ await markAgentForStopping();
2767
+ isAgentFinished = true;
2768
+ break;
2769
+ }
2676
2770
  if (agentResponse === undefined) {
2677
2771
  // If the agent response is undefined, we need to send a message to the agent
2772
+ await markAgentForStopping();
2678
2773
  isAgentFinished = true;
2679
2774
  break;
2680
2775
  }
2681
2776
  if (agentResponse.type === 'finished_task') {
2682
2777
  // If the agent told us that it is finished, we can stop
2778
+ await markAgentForStopping();
2683
2779
  isAgentFinished = true;
2684
2780
  break;
2685
2781
  }
2686
2782
  if (agentResponse.type === 'cell_update' && (agentResponse.cell_update === undefined || agentResponse.cell_update === null)) {
2687
2783
  // If the agent's response is not formatted correctly, stop. This is for typechecking mostly
2784
+ await markAgentForStopping();
2688
2785
  isAgentFinished = true;
2689
2786
  break;
2690
2787
  }
2691
2788
  if (agentResponse.type === 'cell_update' && agentResponse.cell_update) {
2692
2789
  // Run the code and handle any errors
2693
- await (0,_utils_agentActions__WEBPACK_IMPORTED_MODULE_18__.acceptAndRunCellUpdate)(agentResponse.cell_update, notebookTracker, app, previewAICodeToActiveCell, acceptAICode);
2694
- const status = await (0,_utils_agentActions__WEBPACK_IMPORTED_MODULE_18__.retryIfExecutionError)(notebookTracker, app, getDuplicateChatHistoryManager, addAIMessageFromResponseAndUpdateState, sendAgentSmartDebugMessage, previewAICodeToActiveCell, acceptAICode, shouldContinueAgentExecution, finalizeAgentStop, chatHistoryManagerRef);
2790
+ await (0,_utils_agentActions__WEBPACK_IMPORTED_MODULE_18__.acceptAndRunCellUpdate)(agentResponse.cell_update, agentTargetNotebookPanelRef.current);
2791
+ const status = await (0,_utils_agentActions__WEBPACK_IMPORTED_MODULE_18__.retryIfExecutionError)(agentTargetNotebookPanelRef.current, app, sendAgentSmartDebugMessage, shouldContinueAgentExecution, markAgentForStopping, chatHistoryManagerRef);
2695
2792
  if (status === 'interupted') {
2696
2793
  break;
2697
2794
  }
@@ -2711,12 +2808,12 @@ const ChatTaskpane = ({ notebookTracker, renderMimeRegistry, contextManager, app
2711
2808
  sendCellIDOutput = agentResponse.get_cell_output_cell_id;
2712
2809
  }
2713
2810
  if (agentResponse.type === 'run_all_cells') {
2714
- const result = await (0,_utils_agentActions__WEBPACK_IMPORTED_MODULE_18__.runAllCells)(app, notebookTracker);
2811
+ const result = await (0,_utils_agentActions__WEBPACK_IMPORTED_MODULE_18__.runAllCells)(app, agentTargetNotebookPanelRef.current);
2715
2812
  // If run_all_cells resulted in an error, handle it through the error fixup process
2716
2813
  if (!result.success && result.errorMessage && result.errorCellId) {
2717
2814
  // Set the error cell as active so the error retry logic can work with it
2718
- (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_13__.setActiveCellByID)(notebookTracker, result.errorCellId);
2719
- const status = await (0,_utils_agentActions__WEBPACK_IMPORTED_MODULE_18__.retryIfExecutionError)(notebookTracker, app, getDuplicateChatHistoryManager, addAIMessageFromResponseAndUpdateState, sendAgentSmartDebugMessage, previewAICodeToActiveCell, acceptAICode, shouldContinueAgentExecution, finalizeAgentStop, chatHistoryManagerRef);
2815
+ (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_19__.setActiveCellByIDInNotebookPanel)(agentTargetNotebookPanelRef.current, result.errorCellId);
2816
+ const status = await (0,_utils_agentActions__WEBPACK_IMPORTED_MODULE_18__.retryIfExecutionError)(agentTargetNotebookPanelRef.current, app, sendAgentSmartDebugMessage, shouldContinueAgentExecution, markAgentForStopping, chatHistoryManagerRef);
2720
2817
  if (status === 'interupted') {
2721
2818
  break;
2722
2819
  }
@@ -2730,39 +2827,40 @@ const ChatTaskpane = ({ notebookTracker, renderMimeRegistry, contextManager, app
2730
2827
  if (agentExecutionDepth > AGENT_EXECUTION_DEPTH_LIMIT) {
2731
2828
  addAIMessageFromResponseAndUpdateState("Since I've been working for a while now, give my work a review and then tell me how to continue.", 'agent:execution', chatHistoryManager);
2732
2829
  }
2733
- setAgentExecutionStatus('idle');
2830
+ // Use markAgentForStopping for natural conclusion to ensure consistent cleanup
2831
+ await markAgentForStopping();
2734
2832
  };
2735
2833
  const updateCodeDiffStripes = (aiMessage, updateCellID) => {
2736
2834
  if (!aiMessage) {
2737
2835
  return;
2738
2836
  }
2739
- const updateCellCode = (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_13__.getCellCodeByID)(notebookTracker, updateCellID);
2837
+ const updateCellCode = (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_19__.getCellCodeByID)(notebookTracker, updateCellID);
2740
2838
  if (updateCellID === undefined || updateCellCode === undefined) {
2741
2839
  return;
2742
2840
  }
2743
2841
  // Extract the code from the AI's message and then calculate the code diffs
2744
2842
  const aiGeneratedCode = (0,_utils_strings__WEBPACK_IMPORTED_MODULE_16__.getCodeBlockFromMessage)(aiMessage);
2745
2843
  const aiGeneratedCodeCleaned = (0,_utils_strings__WEBPACK_IMPORTED_MODULE_16__.removeMarkdownCodeFormatting)(aiGeneratedCode || '');
2746
- const { unifiedCodeString, unifiedDiffs } = (0,_utils_codeDiff__WEBPACK_IMPORTED_MODULE_19__.getCodeDiffsAndUnifiedCodeString)(updateCellCode, aiGeneratedCodeCleaned);
2844
+ const { unifiedCodeString, unifiedDiffs } = (0,_utils_codeDiff__WEBPACK_IMPORTED_MODULE_20__.getCodeDiffsAndUnifiedCodeString)(updateCellCode, aiGeneratedCodeCleaned);
2747
2845
  // Store the code cell ID where we write the code diffs so that we can
2748
2846
  // accept or reject the code diffs to the correct cell
2749
2847
  cellStateBeforeDiff.current = { codeCellID: updateCellID, code: updateCellCode };
2750
2848
  // Temporarily write the unified code string to the active cell so we can display
2751
2849
  // the code diffs to the user
2752
- (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_13__.writeCodeToCellByID)(notebookTracker, unifiedCodeString, updateCellID);
2850
+ (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_19__.writeCodeToCellByID)(notebookTracker, unifiedCodeString, updateCellID);
2753
2851
  updateCodeCellsExtensions(unifiedDiffs);
2754
2852
  // Briefly highlight the code cell to draw the user's attention to it
2755
- (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_13__.highlightCodeCell)(notebookTracker, updateCellID);
2853
+ (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_19__.highlightCodeCell)(notebookTracker, updateCellID);
2756
2854
  };
2757
2855
  const displayOptimizedChatHistory = chatHistoryManager.getDisplayOptimizedHistory();
2758
2856
  const previewAICodeToActiveCell = () => {
2759
2857
  setCodeReviewStatus('codeCellPreview');
2760
- const activeCellID = (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_13__.getActiveCellID)(notebookTracker);
2858
+ const activeCellID = (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_19__.getActiveCellID)(notebookTracker);
2761
2859
  const lastAIDisplayMessage = chatHistoryManagerRef.current.getLastAIDisplayOptimizedChatItem();
2762
2860
  if (activeCellID === undefined || lastAIDisplayMessage === undefined) {
2763
2861
  return;
2764
2862
  }
2765
- (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_13__.scrollToCell)(notebookTracker, activeCellID, undefined, 'end');
2863
+ (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_19__.scrollToCell)(notebookTracker.currentWidget, activeCellID, undefined, 'end');
2766
2864
  updateCodeDiffStripes(lastAIDisplayMessage.message, activeCellID);
2767
2865
  updateCellToolbarButtons();
2768
2866
  };
@@ -2781,10 +2879,10 @@ const ChatTaskpane = ({ notebookTracker, renderMimeRegistry, contextManager, app
2781
2879
  // Write to the cell that has the code diffs
2782
2880
  writeCodeToCellAndTurnOffDiffs(aiGeneratedCode, targetCellID);
2783
2881
  // Focus on the active cell after the code is written
2784
- const targetCell = (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_13__.getCellByID)(notebookTracker, targetCellID);
2882
+ const targetCell = (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_19__.getCellByID)(notebookTracker, targetCellID);
2785
2883
  if (targetCell) {
2786
2884
  // Make the target cell the active cell
2787
- (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_13__.setActiveCellByID)(notebookTracker, targetCellID);
2885
+ (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_19__.setActiveCellByID)(notebookTracker, targetCellID);
2788
2886
  // Focus on the active cell
2789
2887
  targetCell.activate();
2790
2888
  }
@@ -2810,7 +2908,7 @@ const ChatTaskpane = ({ notebookTracker, renderMimeRegistry, contextManager, app
2810
2908
  updateCodeCellsExtensions(undefined);
2811
2909
  cellStateBeforeDiff.current = undefined;
2812
2910
  if (codeCellID !== undefined) {
2813
- (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_13__.writeCodeToCellByID)(notebookTracker, code, codeCellID);
2911
+ (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_19__.writeCodeToCellByID)(notebookTracker, code, codeCellID);
2814
2912
  updateCellToolbarButtons();
2815
2913
  }
2816
2914
  };
@@ -2821,17 +2919,17 @@ const ChatTaskpane = ({ notebookTracker, renderMimeRegistry, contextManager, app
2821
2919
  the first time we create the chat. Registering the command when it is already created causes
2822
2920
  errors.
2823
2921
  */
2824
- app.commands.addCommand(_commands__WEBPACK_IMPORTED_MODULE_20__.COMMAND_MITO_AI_PREVIEW_LATEST_CODE, {
2922
+ app.commands.addCommand(_commands__WEBPACK_IMPORTED_MODULE_21__.COMMAND_MITO_AI_PREVIEW_LATEST_CODE, {
2825
2923
  execute: () => {
2826
2924
  previewAICodeToActiveCell();
2827
2925
  }
2828
2926
  });
2829
- app.commands.addCommand(_commands__WEBPACK_IMPORTED_MODULE_20__.COMMAND_MITO_AI_APPLY_LATEST_CODE, {
2927
+ app.commands.addCommand(_commands__WEBPACK_IMPORTED_MODULE_21__.COMMAND_MITO_AI_APPLY_LATEST_CODE, {
2830
2928
  execute: () => {
2831
2929
  acceptAICode();
2832
2930
  }
2833
2931
  });
2834
- app.commands.addCommand(_commands__WEBPACK_IMPORTED_MODULE_20__.COMMAND_MITO_AI_REJECT_LATEST_CODE, {
2932
+ app.commands.addCommand(_commands__WEBPACK_IMPORTED_MODULE_21__.COMMAND_MITO_AI_REJECT_LATEST_CODE, {
2835
2933
  execute: () => {
2836
2934
  rejectAICode();
2837
2935
  }
@@ -2840,23 +2938,21 @@ const ChatTaskpane = ({ notebookTracker, renderMimeRegistry, contextManager, app
2840
2938
  Add a new command to the JupyterLab command registry that sends the current chat message.
2841
2939
  We use this to automatically send the message when the user adds an error to the chat.
2842
2940
  */
2843
- app.commands.addCommand(_commands__WEBPACK_IMPORTED_MODULE_20__.COMMAND_MITO_AI_SEND_DEBUG_ERROR_MESSAGE, {
2941
+ app.commands.addCommand(_commands__WEBPACK_IMPORTED_MODULE_21__.COMMAND_MITO_AI_SEND_DEBUG_ERROR_MESSAGE, {
2844
2942
  execute: async (args) => {
2845
2943
  if (args === null || args === void 0 ? void 0 : args.input) {
2846
2944
  await sendSmartDebugMessage(args.input.toString());
2847
2945
  }
2848
2946
  }
2849
2947
  });
2850
- app.commands.addCommand(_commands__WEBPACK_IMPORTED_MODULE_20__.COMMAND_MITO_AI_SEND_EXPLAIN_CODE_MESSAGE, {
2948
+ app.commands.addCommand(_commands__WEBPACK_IMPORTED_MODULE_21__.COMMAND_MITO_AI_SEND_EXPLAIN_CODE_MESSAGE, {
2851
2949
  execute: async () => {
2852
2950
  await sendExplainCodeMessage();
2853
2951
  }
2854
2952
  });
2855
- app.commands.addCommand(_commands__WEBPACK_IMPORTED_MODULE_20__.COMMAND_MITO_AI_SEND_AGENT_MESSAGE, {
2953
+ app.commands.addCommand(_commands__WEBPACK_IMPORTED_MODULE_21__.COMMAND_MITO_AI_SEND_AGENT_MESSAGE, {
2856
2954
  execute: async (args) => {
2857
2955
  if (args === null || args === void 0 ? void 0 : args.input) {
2858
- // Make sure we're in agent mode
2859
- console.log('Setting agent mode to true');
2860
2956
  // If its not already in agent mode, start a new chat in agent mode
2861
2957
  if (!agentModeEnabledRef.current) {
2862
2958
  await startNewChat();
@@ -2871,7 +2967,7 @@ const ChatTaskpane = ({ notebookTracker, renderMimeRegistry, contextManager, app
2871
2967
  /*
2872
2968
  Register the code cell toolbar buttons for accepting and rejecting code.
2873
2969
  */
2874
- app.commands.addCommand(_commands__WEBPACK_IMPORTED_MODULE_20__.COMMAND_MITO_AI_CELL_TOOLBAR_ACCEPT_CODE, {
2970
+ app.commands.addCommand(_commands__WEBPACK_IMPORTED_MODULE_21__.COMMAND_MITO_AI_CELL_TOOLBAR_ACCEPT_CODE, {
2875
2971
  label: `Accept ${operatingSystem === 'mac' ? '⌘Y' : 'Ctrl+Y'}`,
2876
2972
  className: 'text-button-mito-ai button-base button-green',
2877
2973
  caption: 'Accept Code',
@@ -2889,7 +2985,7 @@ const ChatTaskpane = ({ notebookTracker, renderMimeRegistry, contextManager, app
2889
2985
  }
2890
2986
  }
2891
2987
  });
2892
- app.commands.addCommand(_commands__WEBPACK_IMPORTED_MODULE_20__.COMMAND_MITO_AI_CELL_TOOLBAR_REJECT_CODE, {
2988
+ app.commands.addCommand(_commands__WEBPACK_IMPORTED_MODULE_21__.COMMAND_MITO_AI_CELL_TOOLBAR_REJECT_CODE, {
2893
2989
  label: `Reject ${operatingSystem === 'mac' ? '⌘U' : 'Ctrl+U'}`,
2894
2990
  className: 'text-button-mito-ai button-base button-red',
2895
2991
  caption: 'Reject Code',
@@ -2910,13 +3006,13 @@ const ChatTaskpane = ({ notebookTracker, renderMimeRegistry, contextManager, app
2910
3006
  // Register keyboard shortcuts
2911
3007
  const accelYDisposable = app.commands.addKeyBinding({
2912
3008
  command: codeReviewStatus === 'chatPreview' ?
2913
- _commands__WEBPACK_IMPORTED_MODULE_20__.COMMAND_MITO_AI_PREVIEW_LATEST_CODE :
2914
- _commands__WEBPACK_IMPORTED_MODULE_20__.COMMAND_MITO_AI_APPLY_LATEST_CODE,
3009
+ _commands__WEBPACK_IMPORTED_MODULE_21__.COMMAND_MITO_AI_PREVIEW_LATEST_CODE :
3010
+ _commands__WEBPACK_IMPORTED_MODULE_21__.COMMAND_MITO_AI_APPLY_LATEST_CODE,
2915
3011
  keys: ['Accel Y'],
2916
3012
  selector: 'body',
2917
3013
  });
2918
3014
  const accelDDisposable = app.commands.addKeyBinding({
2919
- command: _commands__WEBPACK_IMPORTED_MODULE_20__.COMMAND_MITO_AI_REJECT_LATEST_CODE,
3015
+ command: _commands__WEBPACK_IMPORTED_MODULE_21__.COMMAND_MITO_AI_REJECT_LATEST_CODE,
2920
3016
  keys: ['Accel U'],
2921
3017
  selector: 'body',
2922
3018
  preventDefault: true,
@@ -2933,8 +3029,8 @@ const ChatTaskpane = ({ notebookTracker, renderMimeRegistry, contextManager, app
2933
3029
  // Without this, the user needs to take some action, like switching to a different cell
2934
3030
  // and then switching back in order for the Jupyter to re-evaluate if it should
2935
3031
  // show the toolbar buttons.
2936
- app.commands.notifyCommandChanged(_commands__WEBPACK_IMPORTED_MODULE_20__.COMMAND_MITO_AI_CELL_TOOLBAR_ACCEPT_CODE);
2937
- app.commands.notifyCommandChanged(_commands__WEBPACK_IMPORTED_MODULE_20__.COMMAND_MITO_AI_CELL_TOOLBAR_REJECT_CODE);
3032
+ app.commands.notifyCommandChanged(_commands__WEBPACK_IMPORTED_MODULE_21__.COMMAND_MITO_AI_CELL_TOOLBAR_ACCEPT_CODE);
3033
+ app.commands.notifyCommandChanged(_commands__WEBPACK_IMPORTED_MODULE_21__.COMMAND_MITO_AI_CELL_TOOLBAR_REJECT_CODE);
2938
3034
  };
2939
3035
  const codeDiffStripesCompartments = react__WEBPACK_IMPORTED_MODULE_1___default().useRef(new Map());
2940
3036
  // Function to update the extensions of code cells
@@ -2962,13 +3058,13 @@ const ChatTaskpane = ({ notebookTracker, renderMimeRegistry, contextManager, app
2962
3058
  codeDiffStripesCompartments.current.set(cellId, compartment);
2963
3059
  // Apply the initial configuration
2964
3060
  editorView.dispatch({
2965
- effects: _codemirror_state__WEBPACK_IMPORTED_MODULE_0__.StateEffect.appendConfig.of(compartment.of(unifiedDiffLines !== undefined && isActiveCodeCell ? (0,_CodeDiffDisplay__WEBPACK_IMPORTED_MODULE_21__.codeDiffStripesExtension)({ unifiedDiffLines: unifiedDiffLines }) : [])),
3061
+ effects: _codemirror_state__WEBPACK_IMPORTED_MODULE_0__.StateEffect.appendConfig.of(compartment.of(unifiedDiffLines !== undefined && isActiveCodeCell ? (0,_CodeDiffDisplay__WEBPACK_IMPORTED_MODULE_22__.codeDiffStripesExtension)({ unifiedDiffLines: unifiedDiffLines }) : [])),
2966
3062
  });
2967
3063
  }
2968
3064
  else {
2969
3065
  // Reconfigure the compartment
2970
3066
  editorView.dispatch({
2971
- effects: compartment.reconfigure(unifiedDiffLines !== undefined && isActiveCodeCell ? (0,_CodeDiffDisplay__WEBPACK_IMPORTED_MODULE_21__.codeDiffStripesExtension)({ unifiedDiffLines: unifiedDiffLines }) : []),
3067
+ effects: compartment.reconfigure(unifiedDiffLines !== undefined && isActiveCodeCell ? (0,_CodeDiffDisplay__WEBPACK_IMPORTED_MODULE_22__.codeDiffStripesExtension)({ unifiedDiffLines: unifiedDiffLines }) : []),
2972
3068
  });
2973
3069
  }
2974
3070
  }
@@ -2983,7 +3079,7 @@ const ChatTaskpane = ({ notebookTracker, renderMimeRegistry, contextManager, app
2983
3079
  // In agent mode, we group consecutive error messages together.
2984
3080
  // In chat mode, we display messages individually as they were sent
2985
3081
  if (agentModeEnabled) {
2986
- processedDisplayOptimizedChatHistory = (0,_utils_chatHistory__WEBPACK_IMPORTED_MODULE_22__.processChatHistoryForErrorGrouping)(chatHistoryManager.getDisplayOptimizedHistory());
3082
+ processedDisplayOptimizedChatHistory = (0,_utils_chatHistory__WEBPACK_IMPORTED_MODULE_23__.processChatHistoryForErrorGrouping)(chatHistoryManager.getDisplayOptimizedHistory());
2987
3083
  }
2988
3084
  else {
2989
3085
  processedDisplayOptimizedChatHistory = chatHistoryManager.getDisplayOptimizedHistory();
@@ -2995,16 +3091,16 @@ const ChatTaskpane = ({ notebookTracker, renderMimeRegistry, contextManager, app
2995
3091
  return (react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", { className: "chat-taskpane" },
2996
3092
  react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", { className: "chat-taskpane-header" },
2997
3093
  react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", { className: "chat-taskpane-header-left" },
2998
- react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_components_IconButton__WEBPACK_IMPORTED_MODULE_23__["default"], { icon: react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_jupyterlab_ui_components__WEBPACK_IMPORTED_MODULE_2__.settingsIcon.react, null), title: "Mito AI Settings", onClick: () => {
2999
- void app.commands.execute(_SettingsManager_SettingsManagerPlugin__WEBPACK_IMPORTED_MODULE_24__.COMMAND_MITO_AI_SETTINGS);
3094
+ react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_components_IconButton__WEBPACK_IMPORTED_MODULE_24__["default"], { icon: react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_jupyterlab_ui_components__WEBPACK_IMPORTED_MODULE_2__.settingsIcon.react, null), title: "Mito AI Settings", onClick: () => {
3095
+ void app.commands.execute(_SettingsManager_SettingsManagerPlugin__WEBPACK_IMPORTED_MODULE_25__.COMMAND_MITO_AI_SETTINGS);
3000
3096
  } })),
3001
3097
  react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", { className: "chat-taskpane-header-right" },
3002
- react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_components_IconButton__WEBPACK_IMPORTED_MODULE_23__["default"], { icon: react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_jupyterlab_ui_components__WEBPACK_IMPORTED_MODULE_2__.addIcon.react, null), title: "Start New Chat", onClick: async () => { await startNewChat(); } }),
3003
- react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_components_DropdownMenu__WEBPACK_IMPORTED_MODULE_25__["default"], { trigger: react__WEBPACK_IMPORTED_MODULE_1___default().createElement("button", { className: "icon-button", title: "Chat Threads", onClick: fetchChatThreads },
3098
+ react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_components_IconButton__WEBPACK_IMPORTED_MODULE_24__["default"], { icon: react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_jupyterlab_ui_components__WEBPACK_IMPORTED_MODULE_2__.addIcon.react, null), title: "Start New Chat", onClick: async () => { await startNewChat(); } }),
3099
+ react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_components_DropdownMenu__WEBPACK_IMPORTED_MODULE_26__["default"], { trigger: react__WEBPACK_IMPORTED_MODULE_1___default().createElement("button", { className: "icon-button", title: "Chat Threads", onClick: fetchChatThreads },
3004
3100
  react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_jupyterlab_ui_components__WEBPACK_IMPORTED_MODULE_2__.historyIcon.react, null)), items: chatThreads.length > 0
3005
3101
  ? chatThreads.map(thread => ({
3006
3102
  label: thread.name,
3007
- primaryIcon: activeThreadIdRef.current === thread.thread_id ? _icons__WEBPACK_IMPORTED_MODULE_26__.OpenIndicatorLabIcon.react : undefined,
3103
+ primaryIcon: activeThreadIdRef.current === thread.thread_id ? _icons__WEBPACK_IMPORTED_MODULE_27__.OpenIndicatorLabIcon.react : undefined,
3008
3104
  onClick: () => fetchChatHistoryAndSetActiveThread(thread.thread_id),
3009
3105
  secondaryActions: [
3010
3106
  {
@@ -3023,26 +3119,26 @@ const ChatTaskpane = ({ notebookTracker, renderMimeRegistry, contextManager, app
3023
3119
  displayOptimizedChatHistory.length === 0 &&
3024
3120
  react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", { className: "chat-empty-message" },
3025
3121
  react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", { style: { margin: '0 auto 8px', display: 'block', textAlign: 'center' } },
3026
- react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_icons_MitoLogo__WEBPACK_IMPORTED_MODULE_27__["default"], { width: "60", height: "30" })),
3122
+ react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_icons_MitoLogo__WEBPACK_IMPORTED_MODULE_28__["default"], { width: "60", height: "30" })),
3027
3123
  react__WEBPACK_IMPORTED_MODULE_1___default().createElement("span", { style: { display: 'block', textAlign: 'center', fontWeight: 'bold', fontSize: '20px', marginBottom: '15px' } }, "Data Copilot"),
3028
- react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_CTACarousel__WEBPACK_IMPORTED_MODULE_28__["default"], { app: app })),
3124
+ react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_CTACarousel__WEBPACK_IMPORTED_MODULE_29__["default"], { app: app })),
3029
3125
  processedDisplayOptimizedChatHistory.map((displayOptimizedChat, index) => {
3030
3126
  if (isGroupedErrorMessages(displayOptimizedChat)) {
3031
- return (react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_components_AgentComponents_ErrorFixupToolUI__WEBPACK_IMPORTED_MODULE_29__["default"], { key: index, messages: displayOptimizedChat, renderMimeRegistry: renderMimeRegistry }));
3127
+ return (react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_components_AgentComponents_ErrorFixupToolUI__WEBPACK_IMPORTED_MODULE_30__["default"], { key: index, messages: displayOptimizedChat, renderMimeRegistry: renderMimeRegistry }));
3032
3128
  }
3033
3129
  else {
3034
- return (react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_ChatMessage_ChatMessage__WEBPACK_IMPORTED_MODULE_30__["default"], { key: index, message: displayOptimizedChat.message, promptType: displayOptimizedChat.promptType, agentResponse: displayOptimizedChat.agentResponse, codeCellID: displayOptimizedChat.codeCellID, mitoAIConnectionError: displayOptimizedChat.type === 'connection error', mitoAIConnectionErrorType: displayOptimizedChat.mitoAIConnectionErrorType || null, messageIndex: index, notebookTracker: notebookTracker, renderMimeRegistry: renderMimeRegistry, app: app, isLastAiMessage: index === lastAIMessagesIndex, isLastMessage: index === displayOptimizedChatHistory.length - 1, operatingSystem: operatingSystem, previewAICode: previewAICodeToActiveCell, acceptAICode: acceptAICode, rejectAICode: rejectAICode, onUpdateMessage: handleUpdateMessage, contextManager: contextManager, codeReviewStatus: codeReviewStatus, setNextSteps: setNextSteps, agentModeEnabled: agentModeEnabled, additionalContext: displayOptimizedChat.additionalContext }));
3130
+ return (react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_ChatMessage_ChatMessage__WEBPACK_IMPORTED_MODULE_31__["default"], { key: index, message: displayOptimizedChat.message, promptType: displayOptimizedChat.promptType, agentResponse: displayOptimizedChat.agentResponse, codeCellID: displayOptimizedChat.codeCellID, mitoAIConnectionError: displayOptimizedChat.type === 'connection error', mitoAIConnectionErrorType: displayOptimizedChat.mitoAIConnectionErrorType || null, messageIndex: index, notebookTracker: notebookTracker, renderMimeRegistry: renderMimeRegistry, app: app, isLastAiMessage: index === lastAIMessagesIndex, isLastMessage: index === displayOptimizedChatHistory.length - 1, operatingSystem: operatingSystem, previewAICode: previewAICodeToActiveCell, acceptAICode: acceptAICode, rejectAICode: rejectAICode, onUpdateMessage: handleUpdateMessage, contextManager: contextManager, codeReviewStatus: codeReviewStatus, setNextSteps: setNextSteps, agentModeEnabled: agentModeEnabled, additionalContext: displayOptimizedChat.additionalContext }));
3035
3131
  }
3036
3132
  }).filter(message => message !== null),
3037
3133
  loadingAIResponse &&
3038
3134
  react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", { className: "chat-loading-message" },
3039
3135
  "Thinking ",
3040
- react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_components_LoadingDots__WEBPACK_IMPORTED_MODULE_31__["default"], null)),
3136
+ react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_components_LoadingDots__WEBPACK_IMPORTED_MODULE_32__["default"], null)),
3041
3137
  hasCheckpoint &&
3042
3138
  agentModeEnabled &&
3043
3139
  agentExecutionStatus === 'idle' &&
3044
3140
  displayOptimizedChatHistory.length > 0 && (react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", { className: 'message message-assistant-chat' },
3045
- react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_components_TextAndIconButton__WEBPACK_IMPORTED_MODULE_32__["default"], { text: "Revert changes", icon: _icons_UndoIcon__WEBPACK_IMPORTED_MODULE_33__["default"], title: "Revert changes", onClick: () => {
3141
+ react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_components_TextAndIconButton__WEBPACK_IMPORTED_MODULE_33__["default"], { text: "Revert changes", icon: _icons_UndoIcon__WEBPACK_IMPORTED_MODULE_34__["default"], title: "Revert changes", onClick: () => {
3046
3142
  void (0,_utils_checkpoint__WEBPACK_IMPORTED_MODULE_15__.restoreCheckpoint)(app, notebookTracker, setHasCheckpoint);
3047
3143
  setDisplayedNextStepsIfAvailable(false);
3048
3144
  setHasCheckpoint(false);
@@ -3050,9 +3146,9 @@ const ChatTaskpane = ({ notebookTracker, renderMimeRegistry, contextManager, app
3050
3146
  (0,_utils_scroll__WEBPACK_IMPORTED_MODULE_11__.scrollToDiv)(chatMessagesRef);
3051
3147
  }, variant: "gray", width: "fit-contents", iconPosition: "left" }),
3052
3148
  react__WEBPACK_IMPORTED_MODULE_1___default().createElement("p", { className: "text-muted text-sm" }, "Undo the most recent changes made by the agent"))),
3053
- showRevertQuestionnaire && (react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_ChatMessage_RevertQuestionnaire__WEBPACK_IMPORTED_MODULE_34__["default"], { onDestroy: () => setShowRevertQuestionnaire(false), getDuplicateChatHistoryManager: getDuplicateChatHistoryManager, setChatHistoryManager: setChatHistoryManager }))),
3149
+ showRevertQuestionnaire && (react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_ChatMessage_RevertQuestionnaire__WEBPACK_IMPORTED_MODULE_35__["default"], { onDestroy: () => setShowRevertQuestionnaire(false), getDuplicateChatHistoryManager: getDuplicateChatHistoryManager, setChatHistoryManager: setChatHistoryManager }))),
3054
3150
  displayOptimizedChatHistory.length === 0 && (react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", { className: "suggestions-container" },
3055
- react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_ChatMessage_ScrollableSuggestions__WEBPACK_IMPORTED_MODULE_35__["default"], { onSelectSuggestion: (prompt) => {
3151
+ react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_ChatMessage_ScrollableSuggestions__WEBPACK_IMPORTED_MODULE_36__["default"], { onSelectSuggestion: (prompt) => {
3056
3152
  if (agentModeEnabled) {
3057
3153
  void startAgentExecution(prompt);
3058
3154
  }
@@ -3061,15 +3157,15 @@ const ChatTaskpane = ({ notebookTracker, renderMimeRegistry, contextManager, app
3061
3157
  }
3062
3158
  } }))),
3063
3159
  react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", { className: `connected-input-container ${nextSteps.length > 0 ? 'has-next-steps' : ''}` },
3064
- nextSteps.length > 0 && (react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_components_NextStepsPills__WEBPACK_IMPORTED_MODULE_36__["default"], { nextSteps: nextSteps, onSelectNextStep: agentModeEnabled ? startAgentExecution : sendChatInputMessage, displayedNextStepsIfAvailable: displayedNextStepsIfAvailable, setDisplayedNextStepsIfAvailable: setDisplayedNextStepsIfAvailable })),
3065
- react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_ChatMessage_ChatInput__WEBPACK_IMPORTED_MODULE_37__["default"], { app: app, initialContent: '', placeholder: agentExecutionStatus === 'working' ? 'Agent is working...' :
3160
+ nextSteps.length > 0 && (react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_components_NextStepsPills__WEBPACK_IMPORTED_MODULE_37__["default"], { nextSteps: nextSteps, onSelectNextStep: agentModeEnabled ? startAgentExecution : sendChatInputMessage, displayedNextStepsIfAvailable: displayedNextStepsIfAvailable, setDisplayedNextStepsIfAvailable: setDisplayedNextStepsIfAvailable })),
3161
+ react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_ChatMessage_ChatInput__WEBPACK_IMPORTED_MODULE_38__["default"], { app: app, initialContent: '', placeholder: agentExecutionStatus === 'working' ? `Agent is editing ${(_a = agentTargetNotebookPanelRef.current) === null || _a === void 0 ? void 0 : _a.context.path.split('/').pop()}` :
3066
3162
  agentExecutionStatus === 'stopping' ? 'Agent is stopping...' :
3067
3163
  agentModeEnabled ? 'Ask agent to do anything' :
3068
3164
  displayOptimizedChatHistory.length < 2 ? `Ask question (${operatingSystem === 'mac' ? '⌘' : 'Ctrl'}E), @ to mention`
3069
3165
  : `Ask followup (${operatingSystem === 'mac' ? '⌘' : 'Ctrl'}E), @ to mention`, onSave: agentModeEnabled ? startAgentExecution : sendChatInputMessage, onCancel: undefined, isEditing: false, contextManager: contextManager, notebookTracker: notebookTracker, agentModeEnabled: agentModeEnabled, agentExecutionStatus: agentExecutionStatus })),
3070
3166
  agentExecutionStatus !== 'working' && agentExecutionStatus !== 'stopping' && (react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", { className: "chat-controls" },
3071
3167
  react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", { className: "chat-controls-left" },
3072
- react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_components_ToggleButton__WEBPACK_IMPORTED_MODULE_38__["default"], { leftText: "Chat", leftTooltip: "Chat mode suggests an edit to the active cell and let's you decide to accept or reject it.", rightText: "Agent", rightTooltip: "Agent mode writes and executes code until it's finished your request.", isLeftSelected: !agentModeEnabled, onChange: async (isLeftSelected) => {
3168
+ react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_components_ToggleButton__WEBPACK_IMPORTED_MODULE_39__["default"], { leftText: "Chat", leftTooltip: "Chat mode suggests an edit to the active cell and let's you decide to accept or reject it.", rightText: "Agent", rightTooltip: "Agent mode writes and executes code until it's finished your request.", isLeftSelected: !agentModeEnabled, onChange: async (isLeftSelected) => {
3073
3169
  await startNewChat(); // TODO: delete thread instead of starting new chat
3074
3170
  setAgentModeEnabled(!isLeftSelected);
3075
3171
  // Clear agent checkpoint when switching modes
@@ -3103,9 +3199,9 @@ const ChatTaskpane = ({ notebookTracker, renderMimeRegistry, contextManager, app
3103
3199
  } },
3104
3200
  react__WEBPACK_IMPORTED_MODULE_1___default().createElement("span", { className: "submit-text" }, "Submit"),
3105
3201
  " \u23CE"))),
3106
- (agentExecutionStatus === 'working' || agentExecutionStatus === 'stopping') && (react__WEBPACK_IMPORTED_MODULE_1___default().createElement("button", { className: "button-base button-red stop-agent-button", onClick: markAgentForStopping, disabled: agentExecutionStatus === 'stopping', "data-testid": "stop-agent-button" }, agentExecutionStatus === 'stopping' ? (react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", { className: "stop-agent-button-content" },
3202
+ (agentExecutionStatus === 'working' || agentExecutionStatus === 'stopping') && (react__WEBPACK_IMPORTED_MODULE_1___default().createElement("button", { className: "button-base button-red stop-agent-button", onClick: () => void markAgentForStopping('userStop'), disabled: agentExecutionStatus === 'stopping', "data-testid": "stop-agent-button" }, agentExecutionStatus === 'stopping' ? (react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", { className: "stop-agent-button-content" },
3107
3203
  "Stopping",
3108
- react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_components_LoadingCircle__WEBPACK_IMPORTED_MODULE_39__["default"], null),
3204
+ react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_components_LoadingCircle__WEBPACK_IMPORTED_MODULE_40__["default"], null),
3109
3205
  " ")) : ('Stop Agent')))));
3110
3206
  };
3111
3207
  /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ChatTaskpane);
@@ -3161,7 +3257,7 @@ class ChatWidget extends _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_1__.React
3161
3257
  this._lastErrorChanged = new _lumino_signaling__WEBPACK_IMPORTED_MODULE_3__.Signal(this);
3162
3258
  // Create the websocket client
3163
3259
  this.websocketClient = new _websockets_completions_CompletionsWebsocketClient__WEBPACK_IMPORTED_MODULE_5__.CompletionWebsocketClient({
3164
- serverSettings: options.app.serviceManager.serverSettings
3260
+ serverSettings: options.app.serviceManager.serverSettings,
3165
3261
  });
3166
3262
  this.websocketClient.messages.connect(this.onMessage, this);
3167
3263
  // Initialize the websocket client
@@ -3462,9 +3558,11 @@ const IChatTracker = new _lumino_coreutils__WEBPACK_IMPORTED_MODULE_0__.Token('m
3462
3558
 
3463
3559
  __webpack_require__.r(__webpack_exports__);
3464
3560
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
3465
- /* harmony export */ getBase64EncodedCellOutput: () => (/* binding */ getBase64EncodedCellOutput)
3561
+ /* harmony export */ getBase64EncodedCellOutput: () => (/* binding */ getBase64EncodedCellOutput),
3562
+ /* harmony export */ getBase64EncodedCellOutputInNotebook: () => (/* binding */ getBase64EncodedCellOutputInNotebook)
3466
3563
  /* harmony export */ });
3467
3564
  /* harmony import */ var _utils_notebook__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../utils/notebook */ "./lib/utils/notebook.js");
3565
+ /* harmony import */ var _utils_cellOutput__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../utils/cellOutput */ "./lib/utils/cellOutput.js");
3468
3566
  /* harmony import */ var _restAPI_RestAPI__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../restAPI/RestAPI */ "./lib/restAPI/RestAPI.js");
3469
3567
  /*
3470
3568
  * Copyright (c) Saga Inc.
@@ -3472,20 +3570,23 @@ __webpack_require__.r(__webpack_exports__);
3472
3570
  */
3473
3571
 
3474
3572
 
3573
+
3475
3574
  const getBase64EncodedCellOutput = async (notebookTracker, cellID) => {
3476
- if (cellID === undefined) {
3575
+ const notebookPanel = notebookTracker.currentWidget;
3576
+ return getBase64EncodedCellOutputInNotebook(notebookPanel, cellID);
3577
+ };
3578
+ const getBase64EncodedCellOutputInNotebook = async (notebookPanel, cellID) => {
3579
+ if (cellID === undefined || notebookPanel === null) {
3477
3580
  return undefined;
3478
3581
  }
3479
- // Check if the cell id is part of the notebook
3480
- const cellIndex = (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_0__.getCellIndexByID)(notebookTracker, cellID);
3582
+ const cellIndex = (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_0__.getCellIndexByIDInNotebookPanel)(notebookPanel, cellID);
3481
3583
  if (cellIndex === undefined) {
3482
3584
  // Log that the cell id is not part of the notebook
3483
- console.log(`Cell with id ${cellID} not found in notebook`);
3585
+ console.log(`Cell with id ${cellID} not found in notebook ${notebookPanel.context.path}`);
3484
3586
  void (0,_restAPI_RestAPI__WEBPACK_IMPORTED_MODULE_1__.logEvent)('get_cell_output_requested_non_existent_cell');
3485
3587
  return undefined;
3486
3588
  }
3487
- (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_0__.scrollToCell)(notebookTracker, cellID, 0);
3488
- const activeCellOutput = await (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_0__.getActiveCellOutput)(notebookTracker);
3589
+ const activeCellOutput = await (0,_utils_cellOutput__WEBPACK_IMPORTED_MODULE_2__.getCellOutputByIDInNotebook)(notebookPanel, cellID);
3489
3590
  if (activeCellOutput !== undefined) {
3490
3591
  return activeCellOutput;
3491
3592
  }
@@ -3495,20 +3596,86 @@ const getBase64EncodedCellOutput = async (notebookTracker, cellID) => {
3495
3596
 
3496
3597
  /***/ }),
3497
3598
 
3498
- /***/ "./lib/Extensions/AppBuilder/AppBuilderPlugin.js":
3499
- /*!*******************************************************!*\
3500
- !*** ./lib/Extensions/AppBuilder/AppBuilderPlugin.js ***!
3501
- \*******************************************************/
3599
+ /***/ "./lib/Extensions/AiChat/validationUtils.js":
3600
+ /*!**************************************************!*\
3601
+ !*** ./lib/Extensions/AiChat/validationUtils.js ***!
3602
+ \**************************************************/
3603
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
3604
+
3605
+ __webpack_require__.r(__webpack_exports__);
3606
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
3607
+ /* harmony export */ validateAndCorrectAgentResponse: () => (/* binding */ validateAndCorrectAgentResponse)
3608
+ /* harmony export */ });
3609
+ /*
3610
+ * Copyright (c) Saga Inc.
3611
+ * Distributed under the terms of the GNU Affero General Public License v3.0 License.
3612
+ */
3613
+ /**
3614
+ * Validates and corrects an AgentResponse to ensure it adheres to the expected format.
3615
+ * Handles common mistakes like string instead of array, missing fields, etc.
3616
+ */
3617
+ function validateAndCorrectAgentResponse(agentResponse) {
3618
+ var _a;
3619
+ // Create a copy to avoid mutating the original
3620
+ const correctedResponse = { ...agentResponse };
3621
+ // Ensure type is valid. Default to finished_task if not valid.
3622
+ const validTypes = ['cell_update', 'get_cell_output', 'run_all_cells', 'finished_task'];
3623
+ correctedResponse.type = (correctedResponse.type && validTypes.includes(correctedResponse.type))
3624
+ ? correctedResponse.type
3625
+ : 'finished_task';
3626
+ // Ensure message is a string. Default to empty string if not valid.
3627
+ if (!correctedResponse.message || typeof correctedResponse.message !== 'string') {
3628
+ correctedResponse.message = '';
3629
+ }
3630
+ // Correct get_cell_output_cell_id if present
3631
+ const getCellOutputCellIdType = typeof correctedResponse.get_cell_output_cell_id;
3632
+ correctedResponse.get_cell_output_cell_id = getCellOutputCellIdType === 'string' ? correctedResponse.get_cell_output_cell_id : undefined;
3633
+ // Correct next_steps - handle string to array conversion
3634
+ if (correctedResponse.next_steps !== undefined && correctedResponse.next_steps !== null) {
3635
+ correctedResponse.next_steps = correctStringArray(correctedResponse.next_steps);
3636
+ }
3637
+ // Correct analysis_assumptions - handle string to array conversion
3638
+ if (correctedResponse.analysis_assumptions !== undefined && correctedResponse.analysis_assumptions !== null) {
3639
+ correctedResponse.analysis_assumptions = correctStringArray(correctedResponse.analysis_assumptions);
3640
+ // No empty strings in the assumptions
3641
+ correctedResponse.analysis_assumptions = (_a = correctedResponse.analysis_assumptions) === null || _a === void 0 ? void 0 : _a.filter(assumption => assumption.trim() !== '');
3642
+ }
3643
+ // For now we don't validate the cell_update object itself, as this is more complex and has
3644
+ // not caused issues thus far.
3645
+ return correctedResponse;
3646
+ }
3647
+ /**
3648
+ * Corrects a value to be a string array, handling various input formats.
3649
+ * Handles cases where the AI returns a string instead of an array of strings.
3650
+ */
3651
+ function correctStringArray(value) {
3652
+ // If it's already a valid array of strings, return it
3653
+ if (Array.isArray(value)) {
3654
+ return value;
3655
+ }
3656
+ if (typeof value === 'string') {
3657
+ return [value];
3658
+ }
3659
+ return undefined;
3660
+ }
3661
+
3662
+
3663
+ /***/ }),
3664
+
3665
+ /***/ "./lib/Extensions/AppDeploy/AppDeployPlugin.js":
3666
+ /*!*****************************************************!*\
3667
+ !*** ./lib/Extensions/AppDeploy/AppDeployPlugin.js ***!
3668
+ \*****************************************************/
3502
3669
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
3503
3670
 
3504
3671
  __webpack_require__.r(__webpack_exports__);
3505
3672
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
3506
- /* harmony export */ IAppBuilderService: () => (/* binding */ IAppBuilderService),
3673
+ /* harmony export */ IAppDeployService: () => (/* binding */ IAppDeployService),
3507
3674
  /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
3508
3675
  /* harmony export */ });
3509
3676
  /* harmony import */ var _lumino_coreutils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @lumino/coreutils */ "webpack/sharing/consume/default/@lumino/coreutils");
3510
3677
  /* harmony import */ var _lumino_coreutils__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_lumino_coreutils__WEBPACK_IMPORTED_MODULE_0__);
3511
- /* harmony import */ var _websockets_appBuilder_appBuilderWebsocketClient__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../websockets/appBuilder/appBuilderWebsocketClient */ "./lib/websockets/appBuilder/appBuilderWebsocketClient.js");
3678
+ /* harmony import */ var _websockets_appDeploy_appDeployWebsocketClient__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../websockets/appDeploy/appDeployWebsocketClient */ "./lib/websockets/appDeploy/appDeployWebsocketClient.js");
3512
3679
  /*
3513
3680
  * Copyright (c) Saga Inc.
3514
3681
  * Distributed under the terms of the GNU Affero General Public License v3.0 License.
@@ -3516,49 +3683,49 @@ __webpack_require__.r(__webpack_exports__);
3516
3683
 
3517
3684
 
3518
3685
  /**
3519
- * The token for the AppBuilder service.
3686
+ * The token for the AppDeploy service.
3520
3687
  */
3521
- const IAppBuilderService = new _lumino_coreutils__WEBPACK_IMPORTED_MODULE_0__.Token('mito-ai:IAppBuilderService', 'Token for the AppBuilder service that provides access to the websocket client');
3688
+ const IAppDeployService = new _lumino_coreutils__WEBPACK_IMPORTED_MODULE_0__.Token('mito-ai:IAppDeployService', 'Token for the AppDeploy service that provides access to the websocket client');
3522
3689
  /**
3523
- * Implementation of the AppBuilder service.
3690
+ * Implementation of the AppDeploy service.
3524
3691
  */
3525
- class AppBuilderService {
3692
+ class AppDeployService {
3526
3693
  /**
3527
- * Create a new AppBuilder service.
3694
+ * Create a new AppDeploy service.
3528
3695
  */
3529
3696
  constructor(app) {
3530
3697
  // Create the websocket client with the app's server settings
3531
- this.client = new _websockets_appBuilder_appBuilderWebsocketClient__WEBPACK_IMPORTED_MODULE_1__.AppBuilderWebsocketClient({
3698
+ this.client = new _websockets_appDeploy_appDeployWebsocketClient__WEBPACK_IMPORTED_MODULE_1__.AppDeployWebsocketClient({
3532
3699
  serverSettings: app.serviceManager.serverSettings
3533
3700
  });
3534
3701
  // Initialize the websocket connection in the background
3535
3702
  void this.client.initialize().catch(error => {
3536
- console.error('Failed to initialize AppBuilder websocket client:', error);
3703
+ console.error('Failed to initialize AppDeploy websocket client:', error);
3537
3704
  // We don't need to throw the error since the client will attempt to reconnect when used
3538
3705
  });
3539
3706
  }
3540
3707
  }
3541
3708
  /**
3542
- * The AppBuilder plugin that provides the websocket client.
3709
+ * The AppDeploy plugin that provides the websocket client.
3543
3710
  */
3544
- const AppBuilderPlugin = {
3545
- id: 'mito-ai:app-builder',
3711
+ const AppDeployPlugin = {
3712
+ id: 'mito-ai:app-deploy',
3546
3713
  autoStart: true,
3547
- provides: IAppBuilderService,
3714
+ provides: IAppDeployService,
3548
3715
  activate: (app) => {
3549
- console.log('mito-ai: AppBuilderPlugin activated');
3550
- return new AppBuilderService(app);
3716
+ console.log('mito-ai: AppDeployPlugin activated');
3717
+ return new AppDeployService(app);
3551
3718
  }
3552
3719
  };
3553
- /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AppBuilderPlugin);
3720
+ /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AppDeployPlugin);
3554
3721
 
3555
3722
 
3556
3723
  /***/ }),
3557
3724
 
3558
- /***/ "./lib/Extensions/AppBuilder/DeployAppNotification.js":
3559
- /*!************************************************************!*\
3560
- !*** ./lib/Extensions/AppBuilder/DeployAppNotification.js ***!
3561
- \************************************************************/
3725
+ /***/ "./lib/Extensions/AppDeploy/DeployAppNotification.js":
3726
+ /*!***********************************************************!*\
3727
+ !*** ./lib/Extensions/AppDeploy/DeployAppNotification.js ***!
3728
+ \***********************************************************/
3562
3729
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
3563
3730
 
3564
3731
  __webpack_require__.r(__webpack_exports__);
@@ -3567,51 +3734,92 @@ __webpack_require__.r(__webpack_exports__);
3567
3734
  /* harmony export */ });
3568
3735
  /* harmony import */ var _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @jupyterlab/apputils */ "webpack/sharing/consume/default/@jupyterlab/apputils");
3569
3736
  /* harmony import */ var _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_0__);
3737
+ /* harmony import */ var _AppManager_CheckAppStatusAPI__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../AppManager/CheckAppStatusAPI */ "./lib/Extensions/AppManager/CheckAppStatusAPI.js");
3570
3738
  /*
3571
3739
  * Copyright (c) Saga Inc.
3572
3740
  * Distributed under the terms of the GNU Affero General Public License v3.0 License.
3573
3741
  */
3574
3742
 
3575
- const deployAppNotification = (url) => {
3743
+
3744
+ const deployAppNotification = (url, appManagerService, notificationId) => {
3576
3745
  // Total deployment time in milliseconds (3 minutes = 180000ms)
3577
3746
  const totalDeploymentTime = 180000;
3578
3747
  // Create an array of deployment steps
3579
3748
  const deploymentSteps = [
3580
- "Step 1/7: Preparing your app...",
3581
- "Step 2/7: Assembling clouds...",
3582
- "Step 3/7: Building your app...",
3583
- "Step 4/7: Configuring network settings...",
3584
- "Step 5/7: Adding final touches...",
3585
- "Step 6/7: Running security checks...",
3749
+ "Step 2/7: Preparing your app...",
3750
+ "Step 3/7: Assembling clouds...",
3751
+ "Step 4/7: Building your app...",
3752
+ "Step 5/7: Configuring network settings...",
3753
+ "Step 6/7: Adding final touches...",
3754
+ "Step 7/7: Running security checks...",
3586
3755
  "Deployment complete! Your app is ready."
3587
3756
  ];
3588
- // Create initial "in progress" notification to get notificaiton id
3589
- const notificationId = _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_0__.Notification.emit(deploymentSteps[0], 'in-progress', {
3590
- autoClose: false
3591
- });
3592
3757
  // Calculate time between steps (evenly distribute throughout the total deployment time)
3593
3758
  const stepInterval = totalDeploymentTime / (deploymentSteps.length - 1);
3759
+ let retryCount = 5;
3594
3760
  // Update message at each step interval
3595
- for (let i = 1; i < deploymentSteps.length; i++) {
3761
+ for (let i = 0; i < deploymentSteps.length; i++) {
3596
3762
  setTimeout(() => {
3597
3763
  const isLastStep = i === deploymentSteps.length - 1;
3598
- _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_0__.Notification.update({
3599
- id: notificationId,
3600
- message: deploymentSteps[i],
3601
- type: isLastStep ? 'default' : 'in-progress',
3602
- autoClose: false,
3603
- ...(isLastStep && {
3604
- actions: [
3605
- {
3606
- label: "Launch Application Now",
3607
- displayType: 'accent',
3608
- callback: () => {
3609
- window.open(url, '_blank');
3610
- }
3764
+ if (isLastStep) {
3765
+ const checkUrlAndUpdate = async () => {
3766
+ if (retryCount < 0) {
3767
+ console.log("Retries done");
3768
+ _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_0__.Notification.update({
3769
+ id: notificationId,
3770
+ message: "Unable to deploy. Your app is not reachable",
3771
+ type: 'warning',
3772
+ autoClose: false
3773
+ });
3774
+ return;
3775
+ }
3776
+ try {
3777
+ console.log("Awaiting response");
3778
+ const urlIsUp = await (0,_AppManager_CheckAppStatusAPI__WEBPACK_IMPORTED_MODULE_1__.checkAppStatus)(url, appManagerService);
3779
+ console.log(`App status check result for ${url}: ${urlIsUp}`);
3780
+ if (urlIsUp) {
3781
+ // Update notification with the button
3782
+ _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_0__.Notification.update({
3783
+ id: notificationId,
3784
+ message: deploymentSteps[i],
3785
+ type: 'default',
3786
+ autoClose: false,
3787
+ actions: [
3788
+ {
3789
+ label: "Launch Application Now",
3790
+ displayType: 'accent',
3791
+ callback: () => {
3792
+ window.open(url, '_blank');
3793
+ }
3794
+ }
3795
+ ]
3796
+ });
3611
3797
  }
3612
- ]
3613
- })
3614
- });
3798
+ else {
3799
+ // Retry after 30s
3800
+ console.log("In retry for url to be up");
3801
+ retryCount = retryCount - 1;
3802
+ setTimeout(() => void checkUrlAndUpdate(), 30000);
3803
+ }
3804
+ }
3805
+ catch (error) {
3806
+ // Retry after 30s
3807
+ console.error("Error checking app status:", error);
3808
+ retryCount = retryCount - 1;
3809
+ setTimeout(() => void checkUrlAndUpdate(), 30000);
3810
+ }
3811
+ };
3812
+ void checkUrlAndUpdate();
3813
+ }
3814
+ else {
3815
+ // Regular intermediate step
3816
+ _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_0__.Notification.update({
3817
+ id: notificationId,
3818
+ message: deploymentSteps[i],
3819
+ type: 'in-progress',
3820
+ autoClose: false
3821
+ });
3822
+ }
3615
3823
  }, i * stepInterval);
3616
3824
  }
3617
3825
  };
@@ -3619,27 +3827,147 @@ const deployAppNotification = (url) => {
3619
3827
 
3620
3828
  /***/ }),
3621
3829
 
3622
- /***/ "./lib/Extensions/AppBuilder/NotebookToStreamlit.js":
3623
- /*!**********************************************************!*\
3624
- !*** ./lib/Extensions/AppBuilder/NotebookToStreamlit.js ***!
3625
- \**********************************************************/
3830
+ /***/ "./lib/Extensions/AppDeploy/DeployFilesSelector.js":
3831
+ /*!*********************************************************!*\
3832
+ !*** ./lib/Extensions/AppDeploy/DeployFilesSelector.js ***!
3833
+ \*********************************************************/
3626
3834
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
3627
3835
 
3628
3836
  __webpack_require__.r(__webpack_exports__);
3629
3837
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
3630
- /* harmony export */ convertNotebookToStreamlit: () => (/* binding */ convertNotebookToStreamlit)
3838
+ /* harmony export */ FileUploadPopup: () => (/* binding */ FileUploadPopup)
3631
3839
  /* harmony export */ });
3632
- /* harmony import */ var _jupyterlab_coreutils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @jupyterlab/coreutils */ "webpack/sharing/consume/default/@jupyterlab/coreutils");
3633
- /* harmony import */ var _jupyterlab_coreutils__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_jupyterlab_coreutils__WEBPACK_IMPORTED_MODULE_0__);
3634
- /* harmony import */ var _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @jupyterlab/apputils */ "webpack/sharing/consume/default/@jupyterlab/apputils");
3635
- /* harmony import */ var _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_1__);
3636
- /* harmony import */ var _requirementsUtils__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./requirementsUtils */ "./lib/Extensions/AppBuilder/requirementsUtils.js");
3637
- /* harmony import */ var _fileUtils__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./fileUtils */ "./lib/Extensions/AppBuilder/fileUtils.js");
3638
- /* harmony import */ var _lumino_coreutils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @lumino/coreutils */ "webpack/sharing/consume/default/@lumino/coreutils");
3639
- /* harmony import */ var _lumino_coreutils__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_lumino_coreutils__WEBPACK_IMPORTED_MODULE_2__);
3640
- /* harmony import */ var _DeployAppNotification__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./DeployAppNotification */ "./lib/Extensions/AppBuilder/DeployAppNotification.js");
3641
- /* harmony import */ var _auth__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./auth */ "./lib/Extensions/AppBuilder/auth.js");
3642
- /* harmony import */ var _authPopupUtils__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./authPopupUtils */ "./lib/Extensions/AppBuilder/authPopupUtils.js");
3840
+ /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "webpack/sharing/consume/default/react");
3841
+ /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
3842
+ /* harmony import */ var _style_ConnectionForm_css__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../style/ConnectionForm.css */ "./style/ConnectionForm.css");
3843
+ /* harmony import */ var _style_button_css__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../style/button.css */ "./style/button.css");
3844
+ /* harmony import */ var _style_FilesSelector_css__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../style/FilesSelector.css */ "./style/FilesSelector.css");
3845
+ /* harmony import */ var _jupyterlab_ui_components__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @jupyterlab/ui-components */ "webpack/sharing/consume/default/@jupyterlab/ui-components");
3846
+ /* harmony import */ var _jupyterlab_ui_components__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_jupyterlab_ui_components__WEBPACK_IMPORTED_MODULE_4__);
3847
+ /*
3848
+ * Copyright (c) Saga Inc.
3849
+ * Distributed under the terms of the GNU Affero General Public License v3.0 License.
3850
+ */
3851
+
3852
+
3853
+
3854
+
3855
+
3856
+ const FileIcon = _jupyterlab_ui_components__WEBPACK_IMPORTED_MODULE_4__.fileIcon.react;
3857
+ const FolderIcon = _jupyterlab_ui_components__WEBPACK_IMPORTED_MODULE_4__.folderIcon.react;
3858
+ const CloseIcon = _jupyterlab_ui_components__WEBPACK_IMPORTED_MODULE_4__.closeIcon.react;
3859
+ const FileUploadPopup = ({ filePath, onClose, onSubmit }) => {
3860
+ const [items, setItems] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)([]);
3861
+ const [selectedItems, setSelectedItems] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(new Set());
3862
+ // Figure out current notebook directory
3863
+ const getNotebookDir = () => {
3864
+ if (!filePath)
3865
+ return '';
3866
+ const parts = filePath.split('/');
3867
+ parts.pop(); // remove notebook filename
3868
+ return parts.join('/');
3869
+ };
3870
+ const alwaysSelected = ['requirements.txt', 'app.py'];
3871
+ (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {
3872
+ const nbDir = getNotebookDir();
3873
+ const apiPath = nbDir ? `/api/contents/${nbDir}` : '/api/contents/';
3874
+ fetch(apiPath)
3875
+ .then(res => res.json())
3876
+ .then(data => {
3877
+ const entries = data.content.map((item) => ({
3878
+ name: item.name,
3879
+ type: item.type, // "file" or "directory"
3880
+ }))
3881
+ .sort((a, b) => a.name.localeCompare(b.name));
3882
+ setItems(entries);
3883
+ // Pre-select default files
3884
+ const defaultFiles = new Set();
3885
+ entries.forEach(entry => {
3886
+ if (alwaysSelected.includes(entry.name)) {
3887
+ defaultFiles.add(entry.name);
3888
+ }
3889
+ });
3890
+ setSelectedItems(defaultFiles);
3891
+ })
3892
+ .catch(err => console.error('Error fetching files/dirs:', err));
3893
+ }, []);
3894
+ const handleCheckboxChange = (name) => {
3895
+ setSelectedItems(prev => {
3896
+ const newSet = new Set(prev);
3897
+ if (newSet.has(name))
3898
+ newSet.delete(name);
3899
+ else
3900
+ newSet.add(name);
3901
+ return newSet;
3902
+ });
3903
+ };
3904
+ const handleSelectAll = (checked) => {
3905
+ if (checked) {
3906
+ // select all, nothing excluded
3907
+ setSelectedItems(new Set(items.map(i => i.name)));
3908
+ }
3909
+ else {
3910
+ // keep only alwaysSelected
3911
+ setSelectedItems(new Set(alwaysSelected));
3912
+ }
3913
+ };
3914
+ const handleSubmit = () => {
3915
+ const selectedPaths = Array.from(selectedItems);
3916
+ onSubmit(selectedPaths);
3917
+ onClose();
3918
+ };
3919
+ const allSelected = items.length > 0 && selectedItems.size === items.length;
3920
+ const partiallySelected = selectedItems.size > 0 && selectedItems.size < items.length;
3921
+ return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: "modal-overlay" },
3922
+ react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: "modal-content" },
3923
+ react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: "modal-header" },
3924
+ react__WEBPACK_IMPORTED_MODULE_0___default().createElement("h3", null, "Upload files Required for the App"),
3925
+ react__WEBPACK_IMPORTED_MODULE_0___default().createElement("button", { onClick: onClose, className: "modal-close-button", title: "Close" },
3926
+ react__WEBPACK_IMPORTED_MODULE_0___default().createElement(CloseIcon, null))),
3927
+ react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: "modal-subheader" },
3928
+ react__WEBPACK_IMPORTED_MODULE_0___default().createElement("p", { className: "modal-subtext" }, "Select the files and/or directories that are required to render the app. For example, if your app reads data from a csv file, you must select it here.")),
3929
+ react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: "modal-body" }, items.length === 0 ? (react__WEBPACK_IMPORTED_MODULE_0___default().createElement("p", null, "No items found.")) : (react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null,
3930
+ react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: "files-selector-select-all" },
3931
+ react__WEBPACK_IMPORTED_MODULE_0___default().createElement("label", { className: "checkbox-label" },
3932
+ react__WEBPACK_IMPORTED_MODULE_0___default().createElement("input", { type: "checkbox", checked: allSelected, ref: el => {
3933
+ if (el)
3934
+ el.indeterminate = partiallySelected;
3935
+ }, onChange: e => handleSelectAll(e.target.checked) }),
3936
+ "Select All")),
3937
+ react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: "file-list-scrollable" },
3938
+ react__WEBPACK_IMPORTED_MODULE_0___default().createElement("ul", { className: "file-list" }, items.map((item, index) => (react__WEBPACK_IMPORTED_MODULE_0___default().createElement("li", { key: index },
3939
+ react__WEBPACK_IMPORTED_MODULE_0___default().createElement("label", { className: "checkbox-label" },
3940
+ react__WEBPACK_IMPORTED_MODULE_0___default().createElement("input", { type: "checkbox", checked: selectedItems.has(item.name), onChange: () => handleCheckboxChange(item.name), disabled: alwaysSelected.includes(item.name), title: alwaysSelected.includes(item.name) ? "Required for deploying your app" : undefined }),
3941
+ item.type === 'directory' ? react__WEBPACK_IMPORTED_MODULE_0___default().createElement(FolderIcon, null) : react__WEBPACK_IMPORTED_MODULE_0___default().createElement(FileIcon, null),
3942
+ " ",
3943
+ item.name))))))))),
3944
+ react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: "modal-footer" },
3945
+ react__WEBPACK_IMPORTED_MODULE_0___default().createElement("button", { className: "files-selector-submit-button", onClick: handleSubmit, disabled: selectedItems.size === 0 }, "Deploy App")))));
3946
+ };
3947
+
3948
+
3949
+ /***/ }),
3950
+
3951
+ /***/ "./lib/Extensions/AppDeploy/DeployStreamlitApp.js":
3952
+ /*!********************************************************!*\
3953
+ !*** ./lib/Extensions/AppDeploy/DeployStreamlitApp.js ***!
3954
+ \********************************************************/
3955
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
3956
+
3957
+ __webpack_require__.r(__webpack_exports__);
3958
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
3959
+ /* harmony export */ deployStreamlitApp: () => (/* binding */ deployStreamlitApp)
3960
+ /* harmony export */ });
3961
+ /* harmony import */ var _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @jupyterlab/apputils */ "webpack/sharing/consume/default/@jupyterlab/apputils");
3962
+ /* harmony import */ var _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_0__);
3963
+ /* harmony import */ var _requirementsUtils__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./requirementsUtils */ "./lib/Extensions/AppDeploy/requirementsUtils.js");
3964
+ /* harmony import */ var _fileUtils__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./fileUtils */ "./lib/Extensions/AppDeploy/fileUtils.js");
3965
+ /* harmony import */ var _lumino_coreutils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @lumino/coreutils */ "webpack/sharing/consume/default/@lumino/coreutils");
3966
+ /* harmony import */ var _lumino_coreutils__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_lumino_coreutils__WEBPACK_IMPORTED_MODULE_1__);
3967
+ /* harmony import */ var _DeployAppNotification__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./DeployAppNotification */ "./lib/Extensions/AppDeploy/DeployAppNotification.js");
3968
+ /* harmony import */ var _auth__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./auth */ "./lib/Extensions/AppDeploy/auth.js");
3969
+ /* harmony import */ var _authPopupUtils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./authPopupUtils */ "./lib/Extensions/AppDeploy/authPopupUtils.js");
3970
+ /* harmony import */ var _FilesSelectorUtils__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./FilesSelectorUtils */ "./lib/Extensions/AppDeploy/FilesSelectorUtils.js");
3643
3971
  /*
3644
3972
  * Copyright (c) Saga Inc.
3645
3973
  * Distributed under the terms of the GNU Affero General Public License v3.0 License.
@@ -3653,21 +3981,23 @@ __webpack_require__.r(__webpack_exports__);
3653
3981
 
3654
3982
 
3655
3983
  /*
3656
- This function generates a requirements.txt file that lists the dependencies for the streamlit app
3984
+ This function generates the requirements.txt file needed to host the streamlit app,
3985
+ and deploys it!
3657
3986
  */
3658
- const convertNotebookToStreamlit = async (notebookTracker, appBuilderService) => {
3659
- let jwtToken = await (0,_auth__WEBPACK_IMPORTED_MODULE_3__.getJWTToken)();
3987
+ const deployStreamlitApp = async (notebookTracker, appDeployService, appManagerService) => {
3988
+ let selectedFiles = [];
3989
+ let jwtToken = await (0,_auth__WEBPACK_IMPORTED_MODULE_2__.getJWTToken)();
3660
3990
  if (!jwtToken) {
3661
3991
  // No token found, show authentication popup
3662
3992
  console.log('User not authenticated, redirected to signup');
3663
3993
  try {
3664
- const user = await (0,_authPopupUtils__WEBPACK_IMPORTED_MODULE_4__.showAuthenticationPopup)();
3994
+ const user = await (0,_authPopupUtils__WEBPACK_IMPORTED_MODULE_3__.showAuthenticationPopup)();
3665
3995
  console.log('User authenticated successfully:', user);
3666
3996
  // Try to get the JWT token again after successful authentication
3667
- jwtToken = await (0,_auth__WEBPACK_IMPORTED_MODULE_3__.getJWTToken)();
3997
+ jwtToken = await (0,_auth__WEBPACK_IMPORTED_MODULE_2__.getJWTToken)();
3668
3998
  if (!jwtToken) {
3669
3999
  console.error('JWT token still not available after authentication');
3670
- _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_1__.Notification.emit('Authentication failed - JWT token not found', 'error', {
4000
+ _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_0__.Notification.emit('Authentication failed - JWT token not found', 'error', {
3671
4001
  autoClose: false
3672
4002
  });
3673
4003
  return;
@@ -3684,56 +4014,117 @@ const convertNotebookToStreamlit = async (notebookTracker, appBuilderService) =>
3684
4014
  return;
3685
4015
  }
3686
4016
  const notebookPath = notebookPanel.context.path;
3687
- const notebookName = _jupyterlab_coreutils__WEBPACK_IMPORTED_MODULE_0__.PathExt.basename(notebookPath, '.ipynb');
3688
- console.log('Notebook path:', notebookPath);
3689
- console.log('Notebook name:', notebookName);
3690
- console.log('Current working directory info:', notebookPanel.context);
4017
+ const notificationId = _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_0__.Notification.emit('Step 1/7: Gathering requirements...', 'in-progress', {
4018
+ autoClose: false
4019
+ });
3691
4020
  // Build the requirements.txt file
3692
- console.debug("Building requirements.txt file");
3693
- const requirementsContent = await (0,_requirementsUtils__WEBPACK_IMPORTED_MODULE_5__.generateRequirementsTxt)(notebookTracker);
4021
+ const requirementsContent = await (0,_requirementsUtils__WEBPACK_IMPORTED_MODULE_4__.generateRequirementsTxt)(notebookTracker);
3694
4022
  // Save the files to the current directory
3695
- await (0,_fileUtils__WEBPACK_IMPORTED_MODULE_6__.saveFileWithKernel)(notebookTracker, './requirements.txt', requirementsContent);
4023
+ await (0,_fileUtils__WEBPACK_IMPORTED_MODULE_5__.saveFileWithKernel)(notebookTracker, './requirements.txt', requirementsContent);
4024
+ try {
4025
+ _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_0__.Notification.dismiss(notificationId);
4026
+ selectedFiles = await (0,_FilesSelectorUtils__WEBPACK_IMPORTED_MODULE_6__.fileSelectorPopup)(notebookPath);
4027
+ }
4028
+ catch (error) {
4029
+ console.log('File selection failed:', error);
4030
+ return;
4031
+ }
4032
+ const newNotificationId = _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_0__.Notification.emit("Step 2/7: Preparing your app...", 'in-progress', {
4033
+ autoClose: false
4034
+ });
3696
4035
  // After building the files, we need to send a request to the backend to deploy the app
3697
- if (appBuilderService) {
3698
- try {
3699
- console.log("Sending request to deploy the app");
3700
- // Use the JWT token that was already obtained or refreshed above
3701
- const response = await appBuilderService.client.sendMessage({
3702
- type: 'build-app',
3703
- message_id: _lumino_coreutils__WEBPACK_IMPORTED_MODULE_2__.UUID.uuid4(),
3704
- notebook_path: notebookPath,
3705
- jwt_token: jwtToken
4036
+ try {
4037
+ console.log("Sending request to deploy the app");
4038
+ // Use the JWT token that was already obtained or refreshed above
4039
+ const response = await appDeployService.client.sendMessage({
4040
+ type: 'deploy-app',
4041
+ message_id: _lumino_coreutils__WEBPACK_IMPORTED_MODULE_1__.UUID.uuid4(),
4042
+ notebook_path: notebookPath,
4043
+ jwt_token: jwtToken,
4044
+ selected_files: selectedFiles
4045
+ });
4046
+ if (response.error) {
4047
+ _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_0__.Notification.update({
4048
+ id: newNotificationId,
4049
+ message: response.error.title,
4050
+ type: 'error',
4051
+ autoClose: false
3706
4052
  });
3707
- if (response.error) {
3708
- _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_1__.Notification.emit(response.error.title, 'error', {
3709
- autoClose: false
3710
- });
3711
- }
3712
- else {
3713
- console.log("App deployment response:", response);
3714
- const url = response.url;
3715
- (0,_DeployAppNotification__WEBPACK_IMPORTED_MODULE_7__.deployAppNotification)(url);
3716
- }
3717
4053
  }
3718
- catch (error) {
3719
- // TODO: Do something with the error
3720
- console.error("Error deploying app:", error);
4054
+ else {
4055
+ console.log("App deployment response:", response);
4056
+ const url = response.url;
4057
+ (0,_DeployAppNotification__WEBPACK_IMPORTED_MODULE_7__.deployAppNotification)(url, appManagerService, newNotificationId);
3721
4058
  }
3722
4059
  }
3723
- else {
3724
- console.warn("AppBuilderService not provided - app will not be deployed");
4060
+ catch (error) {
4061
+ // TODO: Do something with the error
4062
+ console.error("Error deploying app:", error);
3725
4063
  }
3726
4064
  };
3727
4065
 
3728
4066
 
3729
4067
  /***/ }),
3730
4068
 
3731
- /***/ "./lib/Extensions/AppBuilder/auth-popup-deploy.js":
4069
+ /***/ "./lib/Extensions/AppDeploy/FilesSelectorUtils.js":
3732
4070
  /*!********************************************************!*\
3733
- !*** ./lib/Extensions/AppBuilder/auth-popup-deploy.js ***!
4071
+ !*** ./lib/Extensions/AppDeploy/FilesSelectorUtils.js ***!
3734
4072
  \********************************************************/
3735
4073
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
3736
4074
 
4075
+ __webpack_require__.r(__webpack_exports__);
4076
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
4077
+ /* harmony export */ fileSelectorPopup: () => (/* binding */ fileSelectorPopup)
4078
+ /* harmony export */ });
4079
+ /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "webpack/sharing/consume/default/react");
4080
+ /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
4081
+ /* harmony import */ var react_dom_client__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-dom/client */ "./node_modules/react-dom/client.js");
4082
+ /* harmony import */ var _DeployFilesSelector__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./DeployFilesSelector */ "./lib/Extensions/AppDeploy/DeployFilesSelector.js");
4083
+ /*
4084
+ * Copyright (c) Saga Inc.
4085
+ * Distributed under the terms of the GNU Affero General Public License v3.0 License.
4086
+ */
4087
+
4088
+
4089
+
4090
+ /**
4091
+ * Shows a file selector popup
4092
+ */
4093
+ const fileSelectorPopup = (notebookPath) => {
4094
+ return new Promise((resolve, reject) => {
4095
+ console.log("Starting file selector for:", notebookPath);
4096
+ // Create a container for the popup
4097
+ const popupContainer = document.createElement('div');
4098
+ popupContainer.id = 'file-selector-popup-container';
4099
+ document.body.appendChild(popupContainer);
4100
+ // Create root
4101
+ const root = (0,react_dom_client__WEBPACK_IMPORTED_MODULE_1__.createRoot)(popupContainer);
4102
+ const handleSubmit = (items) => {
4103
+ // Clean up the popup
4104
+ root.unmount();
4105
+ document.body.removeChild(popupContainer);
4106
+ resolve(items);
4107
+ };
4108
+ const handleClose = () => {
4109
+ // Clean up the popup
4110
+ root.unmount();
4111
+ document.body.removeChild(popupContainer);
4112
+ reject(new Error('File selection cancelled'));
4113
+ };
4114
+ // Render the AuthPopup
4115
+ root.render(react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_DeployFilesSelector__WEBPACK_IMPORTED_MODULE_2__.FileUploadPopup, { filePath: notebookPath, onClose: handleClose, onSubmit: handleSubmit }));
4116
+ });
4117
+ };
4118
+
4119
+
4120
+ /***/ }),
4121
+
4122
+ /***/ "./lib/Extensions/AppDeploy/auth-popup-deploy.js":
4123
+ /*!*******************************************************!*\
4124
+ !*** ./lib/Extensions/AppDeploy/auth-popup-deploy.js ***!
4125
+ \*******************************************************/
4126
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
4127
+
3737
4128
  __webpack_require__.r(__webpack_exports__);
3738
4129
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
3739
4130
  /* harmony export */ AuthPopup: () => (/* binding */ AuthPopup)
@@ -3838,10 +4229,10 @@ const AuthPopup = ({ isOpen, onClose, onSuccess }) => {
3838
4229
 
3839
4230
  /***/ }),
3840
4231
 
3841
- /***/ "./lib/Extensions/AppBuilder/auth.js":
3842
- /*!*******************************************!*\
3843
- !*** ./lib/Extensions/AppBuilder/auth.js ***!
3844
- \*******************************************/
4232
+ /***/ "./lib/Extensions/AppDeploy/auth.js":
4233
+ /*!******************************************!*\
4234
+ !*** ./lib/Extensions/AppDeploy/auth.js ***!
4235
+ \******************************************/
3845
4236
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
3846
4237
 
3847
4238
  __webpack_require__.r(__webpack_exports__);
@@ -3852,7 +4243,7 @@ __webpack_require__.r(__webpack_exports__);
3852
4243
  /* harmony export */ });
3853
4244
  /* harmony import */ var aws_amplify_auth__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! aws-amplify/auth */ "./node_modules/@aws-amplify/core/dist/esm/singleton/apis/fetchAuthSession.mjs");
3854
4245
  /* harmony import */ var aws_amplify_auth__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! aws-amplify/auth */ "./node_modules/@aws-amplify/auth/dist/esm/providers/cognito/apis/signOut.mjs");
3855
- /* harmony import */ var _aws_config__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./aws-config */ "./lib/Extensions/AppBuilder/aws-config.js");
4246
+ /* harmony import */ var _aws_config__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./aws-config */ "./lib/Extensions/AppDeploy/aws-config.js");
3856
4247
  /*
3857
4248
  * Copyright (c) Saga Inc.
3858
4249
  * Distributed under the terms of the GNU Affero General Public License v3.0 License.
@@ -3921,10 +4312,10 @@ const logoutAndClearJWTTokens = async () => {
3921
4312
 
3922
4313
  /***/ }),
3923
4314
 
3924
- /***/ "./lib/Extensions/AppBuilder/authPopupUtils.js":
3925
- /*!*****************************************************!*\
3926
- !*** ./lib/Extensions/AppBuilder/authPopupUtils.js ***!
3927
- \*****************************************************/
4315
+ /***/ "./lib/Extensions/AppDeploy/authPopupUtils.js":
4316
+ /*!****************************************************!*\
4317
+ !*** ./lib/Extensions/AppDeploy/authPopupUtils.js ***!
4318
+ \****************************************************/
3928
4319
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
3929
4320
 
3930
4321
  __webpack_require__.r(__webpack_exports__);
@@ -3934,7 +4325,7 @@ __webpack_require__.r(__webpack_exports__);
3934
4325
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "webpack/sharing/consume/default/react");
3935
4326
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
3936
4327
  /* harmony import */ var react_dom_client__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-dom/client */ "./node_modules/react-dom/client.js");
3937
- /* harmony import */ var _auth_popup_deploy__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./auth-popup-deploy */ "./lib/Extensions/AppBuilder/auth-popup-deploy.js");
4328
+ /* harmony import */ var _auth_popup_deploy__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./auth-popup-deploy */ "./lib/Extensions/AppDeploy/auth-popup-deploy.js");
3938
4329
  /*
3939
4330
  * Copyright (c) Saga Inc.
3940
4331
  * Distributed under the terms of the GNU Affero General Public License v3.0 License.
@@ -3973,10 +4364,10 @@ const showAuthenticationPopup = () => {
3973
4364
 
3974
4365
  /***/ }),
3975
4366
 
3976
- /***/ "./lib/Extensions/AppBuilder/aws-config.js":
3977
- /*!*************************************************!*\
3978
- !*** ./lib/Extensions/AppBuilder/aws-config.js ***!
3979
- \*************************************************/
4367
+ /***/ "./lib/Extensions/AppDeploy/aws-config.js":
4368
+ /*!************************************************!*\
4369
+ !*** ./lib/Extensions/AppDeploy/aws-config.js ***!
4370
+ \************************************************/
3980
4371
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
3981
4372
 
3982
4373
  __webpack_require__.r(__webpack_exports__);
@@ -4016,10 +4407,10 @@ configureAmplify();
4016
4407
 
4017
4408
  /***/ }),
4018
4409
 
4019
- /***/ "./lib/Extensions/AppBuilder/fileUtils.js":
4020
- /*!************************************************!*\
4021
- !*** ./lib/Extensions/AppBuilder/fileUtils.js ***!
4022
- \************************************************/
4410
+ /***/ "./lib/Extensions/AppDeploy/fileUtils.js":
4411
+ /*!***********************************************!*\
4412
+ !*** ./lib/Extensions/AppDeploy/fileUtils.js ***!
4413
+ \***********************************************/
4023
4414
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
4024
4415
 
4025
4416
  __webpack_require__.r(__webpack_exports__);
@@ -4084,10 +4475,10 @@ print(f"File saved successfully to ${filePath}")
4084
4475
 
4085
4476
  /***/ }),
4086
4477
 
4087
- /***/ "./lib/Extensions/AppBuilder/requirementsUtils.js":
4088
- /*!********************************************************!*\
4089
- !*** ./lib/Extensions/AppBuilder/requirementsUtils.js ***!
4090
- \********************************************************/
4478
+ /***/ "./lib/Extensions/AppDeploy/requirementsUtils.js":
4479
+ /*!*******************************************************!*\
4480
+ !*** ./lib/Extensions/AppDeploy/requirementsUtils.js ***!
4481
+ \*******************************************************/
4091
4482
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
4092
4483
 
4093
4484
  __webpack_require__.r(__webpack_exports__);
@@ -4111,70 +4502,77 @@ const generateRequirementsTxt = async (notebookTracker) => {
4111
4502
  // Use the kernel to execute Python code using pipreqs
4112
4503
  const session = notebookPanel.sessionContext.session;
4113
4504
  if (session) {
4114
- // Collect all code in the notebook to analyze with pipreqs
4115
- const notebook = notebookPanel.content;
4116
- let codeContent = '';
4117
- // Gather all code cells content
4118
- notebook.widgets.forEach(cell => {
4119
- if (cell.model.type === 'code') {
4120
- const source = cell.model.sharedModel.source;
4121
- // Filter out lines that start with shell commands
4122
- const filteredLines = source.split('\n').filter(line => {
4123
- const trimmed = line.trim();
4124
- return !trimmed.startsWith('!') && !trimmed.startsWith('%');
4125
- });
4126
- if (filteredLines.length > 0) {
4127
- codeContent += filteredLines.join('\n') + '\n\n';
4128
- }
4129
- }
4130
- });
4131
- // Create Python code to run pipreqs on a temporary directory
4505
+ const appPyPath = `app.py`;
4506
+ // Create Python code to run pipreqs on the app.py file
4132
4507
  const pythonCode = `
4133
4508
  import subprocess
4134
4509
  import os
4135
- import tempfile
4136
-
4137
- # Create a temporary directory for pipreqs to analyze
4138
- with tempfile.TemporaryDirectory() as temp_dir:
4139
- # Save the notebook code to a temporary Python file
4140
- temp_file = os.path.join(temp_dir, "notebook_code.py")
4141
- with open(temp_file, "w") as f:
4142
- f.write("""${codeContent.replace(/\\/g, '\\\\').replace(/"""/g, '\\"\\"\\"')}""")
4143
-
4144
- # Make sure pipreqs is installed. Then
4145
- # 1. Create a requirements.in file
4146
- # 2. From the requirements.in file, generate the requirements.txt file with the canonical PyPI name of the packages
4147
- # and the versions as they exist on the user's terminal
4148
- try:
4149
- # Run pipreqs on the temporary directory
4150
- generate_req_in_file = subprocess.run(
4151
- ['pipreqs', '--savepath', 'requirements.in', '--force', temp_dir],
4152
- capture_output=True,
4153
- text=True
4154
- )
4155
-
4156
- print("Log: ", generate_req_in_file.stderr)
4157
-
4158
- command_for_generating_req_txt_file = r"""
4159
- cat requirements.in | while read line; do \\
4160
- pkg=$(echo $line | cut -d'=' -f1 | tr -d '[:space:]'); \\
4161
- version=$(pip show "$pkg" 2>/dev/null | grep -i '^Version:' | awk '{print $2}'); \\
4162
- name=$(pip show "$pkg" 2>/dev/null | grep -i '^Name:' | awk '{print $2}'); \\
4163
- if [[ -n "$name" && -n "$version" ]]; then echo "$name==$version"; else echo "$line"; fi; \\
4164
- done"""
4165
-
4166
- generate_req_txt_file = subprocess.run(
4167
- command_for_generating_req_txt_file,
4168
- shell=True,
4169
- executable="/bin/bash",
4170
- capture_output=True,
4171
- text=True,
4172
- check=True
4173
- )
4174
- print(generate_req_txt_file.stdout)
4175
-
4176
- except Exception as e:
4177
- print(f"Error running pipreqs: {e}")
4510
+
4511
+ # Check if app.py exists in the notebook directory
4512
+ app_py_path = os.path.join(os.getcwd(), "${appPyPath}")
4513
+ if not os.path.exists(app_py_path):
4514
+ print(f"Error: app.py not found at {app_py_path}")
4515
+ exit(1)
4516
+
4517
+ # Make sure pipreqs is installed. Then
4518
+ # 1. Create a requirements.in file
4519
+ # 2. From the requirements.in file, generate the requirements.txt file with the canonical PyPI name of the packages
4520
+ # and the versions as they exist on the user's terminal
4521
+ try:
4522
+ # Run pipreqs on the directory containing app.py
4523
+ notebook_dir = os.path.dirname(app_py_path)
4524
+ generate_req_in_file = subprocess.run(
4525
+ ['pipreqs', '--encoding=utf-8', '--savepath', 'requirements.in', '--force', notebook_dir],
4526
+ capture_output=True,
4527
+ text=True
4528
+ )
4529
+
4530
+ print("Log: ", generate_req_in_file.stderr)
4531
+
4532
+ # Read requirements.in and process each line
4533
+ requirements_in_path = os.path.join(notebook_dir, 'requirements.in')
4534
+ if os.path.exists(requirements_in_path):
4535
+ with open(requirements_in_path, 'r') as f:
4536
+ lines = f.readlines()
4537
+
4538
+ processed_requirements = []
4539
+ for line in lines:
4540
+ line = line.strip()
4541
+ if not line:
4542
+ continue
4543
+
4544
+ # Extract package name (everything before =)
4545
+ pkg_name = line.split('=')[0].strip()
4546
+
4547
+ # Get package info using pip show
4548
+ try:
4549
+ result = subprocess.run(['pip', 'show', pkg_name],
4550
+ capture_output=True, text=True, check=True)
4551
+ output = result.stdout
4552
+
4553
+ # Parse the output to get Name and Version
4554
+ name = None
4555
+ version = None
4556
+ for output_line in output.split('\\n'):
4557
+ if output_line.startswith('Name:'):
4558
+ name = output_line.split(':', 1)[1].strip()
4559
+ elif output_line.startswith('Version:'):
4560
+ version = output_line.split(':', 1)[1].strip()
4561
+
4562
+ if name and version:
4563
+ processed_requirements.append(f"{name}=={version}")
4564
+ else:
4565
+ processed_requirements.append(line)
4566
+ except subprocess.CalledProcessError:
4567
+ # If pip show fails, use the original line
4568
+ processed_requirements.append(line)
4569
+
4570
+ # Print the processed requirements
4571
+ for req in processed_requirements:
4572
+ print(req)
4573
+
4574
+ except Exception as e:
4575
+ print(f"Error running pipreqs: {e}")
4178
4576
  `;
4179
4577
  const kernel = session.kernel;
4180
4578
  if (kernel === null) {
@@ -4196,6 +4594,7 @@ with tempfile.TemporaryDirectory() as temp_dir:
4196
4594
  console.error(text);
4197
4595
  }
4198
4596
  else {
4597
+ console.log('Found dependencies:\n', text);
4199
4598
  resultText += text;
4200
4599
  }
4201
4600
  }
@@ -4240,7 +4639,7 @@ __webpack_require__.r(__webpack_exports__);
4240
4639
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
4241
4640
  /* harmony import */ var _jupyterlab_ui_components__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @jupyterlab/ui-components */ "webpack/sharing/consume/default/@jupyterlab/ui-components");
4242
4641
  /* harmony import */ var _jupyterlab_ui_components__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_jupyterlab_ui_components__WEBPACK_IMPORTED_MODULE_1__);
4243
- /* harmony import */ var _AppBuilder_auth__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../AppBuilder/auth */ "./lib/Extensions/AppBuilder/auth.js");
4642
+ /* harmony import */ var _AppDeploy_auth__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../AppDeploy/auth */ "./lib/Extensions/AppDeploy/auth.js");
4244
4643
  /* harmony import */ var _ListAppsAPI__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./ListAppsAPI */ "./lib/Extensions/AppManager/ListAppsAPI.js");
4245
4644
  /* harmony import */ var _style_AppsList_css__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../style/AppsList.css */ "./style/AppsList.css");
4246
4645
  /*
@@ -4337,7 +4736,7 @@ const AppsList = ({ appManagerService }) => {
4337
4736
  react__WEBPACK_IMPORTED_MODULE_0__.createElement("button", { onClick: refreshApps, disabled: loading, className: "apps-list-button", title: "Refresh apps" }, loading ? 'Loading...' : 'Refresh'),
4338
4737
  react__WEBPACK_IMPORTED_MODULE_0__.createElement("button", { onClick: () => {
4339
4738
  console.log('Logout clicked');
4340
- void (0,_AppBuilder_auth__WEBPACK_IMPORTED_MODULE_4__.logoutAndClearJWTTokens)();
4739
+ void (0,_AppDeploy_auth__WEBPACK_IMPORTED_MODULE_4__.logoutAndClearJWTTokens)();
4341
4740
  }, className: "apps-list-button", title: "Logout" }, "Logout"))),
4342
4741
  loading ? (react__WEBPACK_IMPORTED_MODULE_0__.createElement("div", { className: "apps-list-loading" }, "Loading apps...")) : error ? (react__WEBPACK_IMPORTED_MODULE_0__.createElement("div", { className: "apps-list-error" },
4343
4742
  "Error: ",
@@ -4360,6 +4759,49 @@ const AppsList = ({ appManagerService }) => {
4360
4759
  };
4361
4760
 
4362
4761
 
4762
+ /***/ }),
4763
+
4764
+ /***/ "./lib/Extensions/AppManager/CheckAppStatusAPI.js":
4765
+ /*!********************************************************!*\
4766
+ !*** ./lib/Extensions/AppManager/CheckAppStatusAPI.js ***!
4767
+ \********************************************************/
4768
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
4769
+
4770
+ __webpack_require__.r(__webpack_exports__);
4771
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
4772
+ /* harmony export */ checkAppStatus: () => (/* binding */ checkAppStatus)
4773
+ /* harmony export */ });
4774
+ /*
4775
+ * Copyright (c) Saga Inc.
4776
+ * Distributed under the terms of the GNU Affero General Public License v3.0 License.
4777
+ */
4778
+ /**
4779
+ * Check if an app URL is accessible through the backend.
4780
+ */
4781
+ const checkAppStatus = async (appUrl, appManagerService) => {
4782
+ try {
4783
+ // Create the request message with proper typing
4784
+ const request = {
4785
+ type: 'check-app-status',
4786
+ app_url: appUrl
4787
+ };
4788
+ // Using websocket service
4789
+ const response = await appManagerService.client.sendMessage(request);
4790
+ // Check if the response indicates an error
4791
+ if (response.error) {
4792
+ console.error('Error checking app status:', response.error.title);
4793
+ return false;
4794
+ }
4795
+ console.log('App is accessible:', response.is_accessible);
4796
+ return response.is_accessible;
4797
+ }
4798
+ catch (error) {
4799
+ console.error('Error checking app status:', error);
4800
+ return false;
4801
+ }
4802
+ };
4803
+
4804
+
4363
4805
  /***/ }),
4364
4806
 
4365
4807
  /***/ "./lib/Extensions/AppManager/ListAppsAPI.js":
@@ -4374,7 +4816,7 @@ __webpack_require__.r(__webpack_exports__);
4374
4816
  /* harmony export */ isGetAppsFailure: () => (/* binding */ isGetAppsFailure),
4375
4817
  /* harmony export */ isGetAppsSuccess: () => (/* binding */ isGetAppsSuccess)
4376
4818
  /* harmony export */ });
4377
- /* harmony import */ var _AppBuilder_auth__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../AppBuilder/auth */ "./lib/Extensions/AppBuilder/auth.js");
4819
+ /* harmony import */ var _AppDeploy_auth__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../AppDeploy/auth */ "./lib/Extensions/AppDeploy/auth.js");
4378
4820
  /*
4379
4821
  * Copyright (c) Saga Inc.
4380
4822
  * Distributed under the terms of the GNU Affero General Public License v3.0 License.
@@ -4389,7 +4831,7 @@ const isGetAppsFailure = (response) => {
4389
4831
  };
4390
4832
  const fetchUserApps = async (appManagerService) => {
4391
4833
  try {
4392
- const jwtToken = await (0,_AppBuilder_auth__WEBPACK_IMPORTED_MODULE_0__.getJWTToken)();
4834
+ const jwtToken = await (0,_AppDeploy_auth__WEBPACK_IMPORTED_MODULE_0__.getJWTToken)();
4393
4835
  if (!jwtToken) {
4394
4836
  return {
4395
4837
  success: false,
@@ -4530,6 +4972,211 @@ const ManageAppsPlugin = {
4530
4972
  /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ManageAppsPlugin);
4531
4973
 
4532
4974
 
4975
+ /***/ }),
4976
+
4977
+ /***/ "./lib/Extensions/AppPreview/StreamlitPreviewPlugin.js":
4978
+ /*!*************************************************************!*\
4979
+ !*** ./lib/Extensions/AppPreview/StreamlitPreviewPlugin.js ***!
4980
+ \*************************************************************/
4981
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
4982
+
4983
+ __webpack_require__.r(__webpack_exports__);
4984
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
4985
+ /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
4986
+ /* harmony export */ });
4987
+ /* harmony import */ var _jupyterlab_notebook__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @jupyterlab/notebook */ "webpack/sharing/consume/default/@jupyterlab/notebook");
4988
+ /* harmony import */ var _jupyterlab_notebook__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_jupyterlab_notebook__WEBPACK_IMPORTED_MODULE_0__);
4989
+ /* harmony import */ var _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @jupyterlab/apputils */ "webpack/sharing/consume/default/@jupyterlab/apputils");
4990
+ /* harmony import */ var _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_1__);
4991
+ /* harmony import */ var _jupyterlab_coreutils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @jupyterlab/coreutils */ "webpack/sharing/consume/default/@jupyterlab/coreutils");
4992
+ /* harmony import */ var _jupyterlab_coreutils__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_jupyterlab_coreutils__WEBPACK_IMPORTED_MODULE_2__);
4993
+ /* harmony import */ var _lumino_widgets__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @lumino/widgets */ "webpack/sharing/consume/default/@lumino/widgets");
4994
+ /* harmony import */ var _lumino_widgets__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_lumino_widgets__WEBPACK_IMPORTED_MODULE_3__);
4995
+ /* harmony import */ var _restAPI_RestAPI__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../../restAPI/RestAPI */ "./lib/restAPI/RestAPI.js");
4996
+ /* harmony import */ var _AppDeploy_DeployStreamlitApp__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../AppDeploy/DeployStreamlitApp */ "./lib/Extensions/AppDeploy/DeployStreamlitApp.js");
4997
+ /* harmony import */ var _AppDeploy_AppDeployPlugin__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../AppDeploy/AppDeployPlugin */ "./lib/Extensions/AppDeploy/AppDeployPlugin.js");
4998
+ /* harmony import */ var _AppManager_ManageAppsPlugin__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../AppManager/ManageAppsPlugin */ "./lib/Extensions/AppManager/ManageAppsPlugin.js");
4999
+ /* harmony import */ var _commands__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../commands */ "./lib/commands.js");
5000
+ /* harmony import */ var _icons__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../../icons */ "./lib/icons/index.js");
5001
+ /* harmony import */ var _style_StreamlitPreviewPlugin_css__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../../style/StreamlitPreviewPlugin.css */ "./style/StreamlitPreviewPlugin.css");
5002
+ /* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./utils */ "./lib/Extensions/AppPreview/utils.js");
5003
+ /*
5004
+ * Copyright (c) Saga Inc.
5005
+ * Distributed under the terms of the GNU Affero General Public License v3.0 License.
5006
+ */
5007
+
5008
+
5009
+
5010
+
5011
+
5012
+
5013
+
5014
+
5015
+
5016
+
5017
+
5018
+
5019
+
5020
+
5021
+ /**
5022
+ * Simple HTML widget for displaying iframe content.
5023
+ */
5024
+ class IFrameWidget extends _lumino_widgets__WEBPACK_IMPORTED_MODULE_3__.Widget {
5025
+ constructor(url) {
5026
+ super();
5027
+ this.addClass('jp-iframe-widget');
5028
+ const iframe = document.createElement('iframe');
5029
+ iframe.src = url;
5030
+ iframe.style.width = '100%';
5031
+ iframe.style.height = '100%';
5032
+ iframe.style.border = 'none';
5033
+ this.node.appendChild(iframe);
5034
+ }
5035
+ setUrl(url) {
5036
+ const iframe = this.node.querySelector('iframe');
5037
+ if (iframe) {
5038
+ iframe.src = url;
5039
+ }
5040
+ }
5041
+ }
5042
+ /**
5043
+ * The streamlit preview plugin.
5044
+ */
5045
+ const StreamlitPreviewPlugin = {
5046
+ id: 'mito-ai:streamlit-preview',
5047
+ autoStart: true,
5048
+ requires: [_jupyterlab_notebook__WEBPACK_IMPORTED_MODULE_0__.INotebookTracker, _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_1__.ICommandPalette, _AppDeploy_AppDeployPlugin__WEBPACK_IMPORTED_MODULE_5__.IAppDeployService, _AppManager_ManageAppsPlugin__WEBPACK_IMPORTED_MODULE_6__.IAppManagerService],
5049
+ activate: (app, notebookTracker, palette, appDeployService, appManagerService) => {
5050
+ console.log('mito-ai: StreamlitPreviewPlugin activated');
5051
+ // Add command to command palette
5052
+ app.commands.addCommand(_commands__WEBPACK_IMPORTED_MODULE_7__.COMMAND_MITO_AI_PREVIEW_AS_STREAMLIT, {
5053
+ label: 'Preview as Streamlit',
5054
+ caption: 'Convert current notebook to Streamlit app and preview it',
5055
+ execute: async () => {
5056
+ await previewNotebookAsStreamlit(app, notebookTracker, appDeployService, appManagerService);
5057
+ }
5058
+ });
5059
+ // Add to command palette
5060
+ palette.addItem({
5061
+ command: _commands__WEBPACK_IMPORTED_MODULE_7__.COMMAND_MITO_AI_PREVIEW_AS_STREAMLIT,
5062
+ category: 'Mito AI'
5063
+ });
5064
+ }
5065
+ };
5066
+ /**
5067
+ * Preview the current notebook as a Streamlit app.
5068
+ */
5069
+ async function previewNotebookAsStreamlit(app, notebookTracker, appDeployService, appManagerService) {
5070
+ const notebookPanel = notebookTracker.currentWidget;
5071
+ if (!notebookPanel) {
5072
+ _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_1__.Notification.error('No notebook is currently active');
5073
+ return;
5074
+ }
5075
+ // First save the notebook to ensure the app is up to date
5076
+ await notebookPanel.context.save();
5077
+ const notebookPath = notebookPanel.context.path;
5078
+ const notebookName = _jupyterlab_coreutils__WEBPACK_IMPORTED_MODULE_2__.PathExt.basename(notebookPath, '.ipynb');
5079
+ let globalNotificationId;
5080
+ try {
5081
+ const { previewData, notificationId } = await (0,_utils__WEBPACK_IMPORTED_MODULE_8__.startStreamlitPreviewAndNotify)(notebookPath);
5082
+ globalNotificationId = notificationId;
5083
+ // Create iframe widget
5084
+ // TODO: Instead of having this widget creation code in the previewNotebookAsStreamlit function,
5085
+ // I wonder if we can make it part of the StreamlitPreviewPlugin. What we want is the following:
5086
+ // a react component that takes the app, notebookTracker, and appDeployService as a prop and is
5087
+ // already set up with this layout. Each time it opens, we're just deciding which notebook to display.
5088
+ const iframeWidget = new IFrameWidget(previewData.url);
5089
+ // Create main area widget
5090
+ const widget = new _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_1__.MainAreaWidget({ content: iframeWidget });
5091
+ widget.title.label = `App Preview (${notebookName})`;
5092
+ widget.title.closable = true;
5093
+ // Add toolbar button to the MainAreaWidget's toolbar
5094
+ const deployButton = new _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_1__.ToolbarButton({
5095
+ className: 'text-button-mito-ai button-base button-small jp-ToolbarButton mito-deploy-button',
5096
+ onClick: () => {
5097
+ void (0,_AppDeploy_DeployStreamlitApp__WEBPACK_IMPORTED_MODULE_9__.deployStreamlitApp)(notebookTracker, appDeployService, appManagerService);
5098
+ },
5099
+ tooltip: 'Deploy Streamlit App',
5100
+ label: 'Deploy App',
5101
+ icon: _icons__WEBPACK_IMPORTED_MODULE_10__.DeployLabIcon,
5102
+ iconClass: 'mito-ai-deploy-icon'
5103
+ });
5104
+ // Add toolbar button to the MainAreaWidget's toolbar
5105
+ const refreshButton = new _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_1__.ToolbarButton({
5106
+ className: 'text-button-mito-ai button-base button-small jp-ToolbarButton mito-deploy-button',
5107
+ onClick: () => {
5108
+ void (0,_utils__WEBPACK_IMPORTED_MODULE_8__.startStreamlitPreviewAndNotify)(notebookPath, true);
5109
+ },
5110
+ tooltip: 'Rebuild Streamlit App',
5111
+ label: 'Rebuild App',
5112
+ icon: _icons__WEBPACK_IMPORTED_MODULE_10__.DeployLabIcon,
5113
+ iconClass: 'mito-ai-deploy-icon'
5114
+ });
5115
+ // Insert the button into the toolbar
5116
+ widget.toolbar.insertAfter('spacer', 'refresh-app-button', refreshButton);
5117
+ widget.toolbar.insertAfter('spacer', 'deploy-app-button', deployButton);
5118
+ // Handle widget disposal
5119
+ widget.disposed.connect(() => {
5120
+ console.log('Widget disposed, stopping preview');
5121
+ void (0,_restAPI_RestAPI__WEBPACK_IMPORTED_MODULE_11__.stopStreamlitPreview)(previewData.id);
5122
+ });
5123
+ // Add widget to main area with split-right mode
5124
+ app.shell.add(widget, 'main', {
5125
+ mode: 'split-right',
5126
+ ref: notebookPanel.id
5127
+ });
5128
+ }
5129
+ catch (error) {
5130
+ console.error('Error starting streamlit preview:', error);
5131
+ // Update notification to error
5132
+ if (globalNotificationId) {
5133
+ _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_1__.Notification.update({
5134
+ id: globalNotificationId,
5135
+ message: `Failed to start preview: ${error instanceof Error ? error.message : 'Unknown error'}`,
5136
+ type: 'error',
5137
+ autoClose: false
5138
+ });
5139
+ }
5140
+ }
5141
+ }
5142
+ /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (StreamlitPreviewPlugin);
5143
+
5144
+
5145
+ /***/ }),
5146
+
5147
+ /***/ "./lib/Extensions/AppPreview/utils.js":
5148
+ /*!********************************************!*\
5149
+ !*** ./lib/Extensions/AppPreview/utils.js ***!
5150
+ \********************************************/
5151
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
5152
+
5153
+ __webpack_require__.r(__webpack_exports__);
5154
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
5155
+ /* harmony export */ startStreamlitPreviewAndNotify: () => (/* binding */ startStreamlitPreviewAndNotify)
5156
+ /* harmony export */ });
5157
+ /* harmony import */ var _restAPI_RestAPI__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../restAPI/RestAPI */ "./lib/restAPI/RestAPI.js");
5158
+ /* harmony import */ var _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @jupyterlab/apputils */ "webpack/sharing/consume/default/@jupyterlab/apputils");
5159
+ /* harmony import */ var _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_0__);
5160
+ /*
5161
+ * Copyright (c) Saga Inc.
5162
+ * Distributed under the terms of the GNU Affero General Public License v3.0 License.
5163
+ */
5164
+
5165
+
5166
+ const startStreamlitPreviewAndNotify = async (notebookPath, force_recreate = false) => {
5167
+ const notificationId = _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_0__.Notification.emit('Building App Preview...', 'in-progress', { autoClose: false });
5168
+ const previewData = await (0,_restAPI_RestAPI__WEBPACK_IMPORTED_MODULE_1__.startStreamlitPreview)(notebookPath, force_recreate);
5169
+ // Update notification to success
5170
+ _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_0__.Notification.update({
5171
+ id: notificationId,
5172
+ message: 'Streamlit preview started successfully!',
5173
+ type: 'default',
5174
+ autoClose: 5 * 1000
5175
+ });
5176
+ return { previewData, notificationId };
5177
+ };
5178
+
5179
+
4533
5180
  /***/ }),
4534
5181
 
4535
5182
  /***/ "./lib/Extensions/ContextManager/ContextManagerPlugin.js":
@@ -4565,37 +5212,31 @@ __webpack_require__.r(__webpack_exports__);
4565
5212
  const IContextManager = new _lumino_coreutils__WEBPACK_IMPORTED_MODULE_1__.Token('mito-ai:IContextManager');
4566
5213
  class ContextManager {
4567
5214
  constructor(app, notebookTracker) {
4568
- this._variables = [];
4569
- this._files = [];
4570
- // Setup the kernel listener to update context as kernel messages are received
4571
- this.setupKernelListener(app, notebookTracker);
4572
- }
4573
- get variables() {
4574
- return this._variables;
4575
- }
4576
- setVariables(newVars) {
4577
- this._variables = newVars;
4578
- }
4579
- get files() {
4580
- return this._files;
4581
- }
4582
- setFiles(newFiles) {
4583
- this._files = newFiles;
4584
- }
4585
- // Setup kernel execution listener
4586
- setupKernelListener(app, notebookTracker) {
4587
- notebookTracker.currentChanged.connect(async (tracker, notebookPanel) => {
4588
- if (!notebookPanel) {
5215
+ this.notebookContexts = new Map();
5216
+ this._startKernelListener = async (app, notebookPanel) => {
5217
+ if (notebookPanel === null) {
4589
5218
  return;
4590
5219
  }
4591
- // Listen for kernel refresh events
5220
+ // Initialize context for this notebook if it doesn't exist
5221
+ if (!this.notebookContexts.has(notebookPanel.id)) {
5222
+ this.notebookContexts.set(notebookPanel.id, { variables: [], files: [] });
5223
+ }
5224
+ // As soon as the notebook is opened, fetch the files since these are not related to the kernel,
5225
+ // but to the notebook itself. This is useful so we can tell the agent which files are available
5226
+ // or let the user select a file from the dropdown menu before the kernel is started.
5227
+ // We use the notebookPanel.id to identify the notebook because we might need to access
5228
+ // NotebookContext even before the kernel is started. For example, to figure out
5229
+ // which files are available.
5230
+ const updatedFiles = await (0,_FileInspector__WEBPACK_IMPORTED_MODULE_2__.getFiles)(app, notebookPanel);
5231
+ this.updateNotebookFiles(notebookPanel.id, updatedFiles);
5232
+ // Listen for kernel restart or shut down events and clear the variables for this notebook
4592
5233
  notebookPanel.context.sessionContext.statusChanged.connect((sender, status) => {
4593
- if (status === 'restarting') {
4594
- this.setVariables([]); // Clear variables on kernel refresh
5234
+ if (status === 'restarting' || status === 'terminating' || status === 'unknown') {
5235
+ // Clear the variables for this specific notebook, but don't clear the files
5236
+ // as they have not changed.
5237
+ this.updateNotebookVariables(notebookPanel.id, []); // Clear variables for this specific notebook
4595
5238
  }
4596
5239
  });
4597
- // As soon as the notebook is opened, fetch the files so we don't have to wait for the first message.
4598
- await (0,_FileInspector__WEBPACK_IMPORTED_MODULE_2__.fetchFilesAndUpdateState)(app, notebookTracker, this.setFiles.bind(this));
4599
5240
  // Listen to kernel messages
4600
5241
  notebookPanel.context.sessionContext.iopubMessage.connect(async (sender, msg) => {
4601
5242
  // Watch for execute_input messages, which indicate is a request to execute code.
@@ -4603,11 +5244,46 @@ class ContextManager {
4603
5244
  // from the kernel when a code cell prints a value to the output cell, which is not what we want.
4604
5245
  // TODO: Check if there is a race condition where we might end up fetching variables before the
4605
5246
  // code is executed. I don't think this is the case because the kernel runs in one thread I believe.
5247
+ // TODO: Eventually we should create a document manager listener so if the user uploads a new file
5248
+ // to jupyter, we can update the available files even if they have not executed a kernel message.
4606
5249
  if (msg.header.msg_type === 'execute_input') {
4607
- await (0,_VariableInspector__WEBPACK_IMPORTED_MODULE_3__.fetchVariablesAndUpdateState)(notebookPanel, this.setVariables.bind(this));
4608
- await (0,_FileInspector__WEBPACK_IMPORTED_MODULE_2__.fetchFilesAndUpdateState)(app, notebookTracker, this.setFiles.bind(this));
5250
+ void (0,_VariableInspector__WEBPACK_IMPORTED_MODULE_3__.fetchVariablesAndUpdateState)(notebookPanel, this.updateNotebookVariables.bind(this, notebookPanel.id));
5251
+ const updatedFiles = await (0,_FileInspector__WEBPACK_IMPORTED_MODULE_2__.getFiles)(app, notebookPanel);
5252
+ this.updateNotebookFiles(notebookPanel.id, updatedFiles);
4609
5253
  }
4610
5254
  });
5255
+ };
5256
+ this.notebookTracker = notebookTracker;
5257
+ // Setup the kernel listener to update context as kernel messages are received
5258
+ this.setupKernelListener(app, notebookTracker);
5259
+ }
5260
+ getNotebookContext(notebookId) {
5261
+ return this.notebookContexts.get(notebookId);
5262
+ }
5263
+ getActiveNotebookContext() {
5264
+ const activeNotebook = this.notebookTracker.currentWidget;
5265
+ if (!activeNotebook)
5266
+ return undefined;
5267
+ return this.getNotebookContext(activeNotebook.id);
5268
+ }
5269
+ updateNotebookVariables(notebookID, variables) {
5270
+ const context = this.notebookContexts.get(notebookID) || { variables: [], files: [] };
5271
+ context.variables = variables;
5272
+ this.notebookContexts.set(notebookID, context);
5273
+ }
5274
+ updateNotebookFiles(notebookID, files) {
5275
+ const context = this.notebookContexts.get(notebookID) || { variables: [], files: [] };
5276
+ context.files = files;
5277
+ this.notebookContexts.set(notebookID, context);
5278
+ }
5279
+ // Setup kernel execution listener
5280
+ setupKernelListener(app, notebookTracker) {
5281
+ // Start the kernel listener for the currently active notebook
5282
+ const notebookPanel = notebookTracker.currentWidget;
5283
+ void this._startKernelListener(app, notebookPanel);
5284
+ // Update the kernel listener whenever the active notebook changes
5285
+ notebookTracker.currentChanged.connect(async (_, notebookPanel) => {
5286
+ void this._startKernelListener(app, notebookPanel);
4611
5287
  });
4612
5288
  }
4613
5289
  }
@@ -4634,7 +5310,7 @@ const ContextManagerPlugin = {
4634
5310
 
4635
5311
  __webpack_require__.r(__webpack_exports__);
4636
5312
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
4637
- /* harmony export */ fetchFilesAndUpdateState: () => (/* binding */ fetchFilesAndUpdateState)
5313
+ /* harmony export */ getFiles: () => (/* binding */ getFiles)
4638
5314
  /* harmony export */ });
4639
5315
  /* harmony import */ var _jupyterlab_coreutils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @jupyterlab/coreutils */ "webpack/sharing/consume/default/@jupyterlab/coreutils");
4640
5316
  /* harmony import */ var _jupyterlab_coreutils__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_jupyterlab_coreutils__WEBPACK_IMPORTED_MODULE_0__);
@@ -4646,15 +5322,9 @@ __webpack_require__.r(__webpack_exports__);
4646
5322
  /*
4647
5323
  Fetches all files in the current directory and updates the state of the files.
4648
5324
  */
4649
- const fetchFilesAndUpdateState = async (app, notebookTracker, setFiles) => {
5325
+ const getFiles = async (app, notebookPanel) => {
4650
5326
  const fileManager = app.serviceManager.contents;
4651
- // Get the current notebook
4652
- const currentNotebook = notebookTracker.currentWidget;
4653
- if (!currentNotebook) {
4654
- return;
4655
- }
4656
- // Get the directory path using PathExt.dirname from @jupyterlab/coreutils
4657
- const relativeNotebookPath = currentNotebook.context.path;
5327
+ const relativeNotebookPath = notebookPanel.context.path;
4658
5328
  const relativeDirectoryPath = _jupyterlab_coreutils__WEBPACK_IMPORTED_MODULE_0__.PathExt.dirname(relativeNotebookPath);
4659
5329
  try {
4660
5330
  const contents = await fileManager.get(relativeDirectoryPath);
@@ -4673,16 +5343,16 @@ const fetchFilesAndUpdateState = async (app, notebookTracker, setFiles) => {
4673
5343
  file_name: file.name
4674
5344
  }));
4675
5345
  // Update the state of the files
4676
- setFiles(files);
5346
+ return files;
4677
5347
  }
4678
5348
  else {
4679
5349
  // If the contents are not a directory, set the files to an empty array
4680
- setFiles([]);
5350
+ return [];
4681
5351
  }
4682
5352
  }
4683
5353
  catch (error) {
4684
5354
  console.error('Error listing directory contents:', error);
4685
- return;
5355
+ return [];
4686
5356
  }
4687
5357
  };
4688
5358
 
@@ -4819,7 +5489,9 @@ def structured_globals():
4819
5489
 
4820
5490
  print(structured_globals())
4821
5491
  `;
4822
- // Function to fetch variables and sync with the frontend
5492
+ /*
5493
+ Function to fetch variables and sync with the frontend
5494
+ */
4823
5495
  function fetchVariablesAndUpdateState(notebookPanel, setVariables) {
4824
5496
  var _a;
4825
5497
  const kernel = (_a = notebookPanel.context.sessionContext.session) === null || _a === void 0 ? void 0 : _a.kernel;
@@ -4835,7 +5507,7 @@ function fetchVariablesAndUpdateState(notebookPanel, setVariables) {
4835
5507
  // Listen for the output from the kernel
4836
5508
  future.onIOPub = (msg) => {
4837
5509
  // A 'stream' message represents standard output (stdout) or standard error (stderr) produced
4838
- // during the execution of code in the kernel.
5510
+ // during the execution of code in the kernel.
4839
5511
  if (_jupyterlab_services__WEBPACK_IMPORTED_MODULE_0__.KernelMessage.isStreamMsg(msg)) {
4840
5512
  if (msg.content.name === 'stdout') {
4841
5513
  try {
@@ -6214,10 +6886,11 @@ const ContextManagerSection = ({ contextManager }) => {
6214
6886
  // Force a re-render by toggling the state
6215
6887
  setRefreshKey(prev => prev + 1);
6216
6888
  };
6889
+ const activeNotebookContext = contextManager.getActiveNotebookContext();
6217
6890
  const copyContextManagerToClipboard = async () => {
6218
6891
  const jsonContent = JSON.stringify({
6219
- variables: contextManager.variables,
6220
- files: contextManager.files
6892
+ variables: activeNotebookContext === null || activeNotebookContext === void 0 ? void 0 : activeNotebookContext.variables,
6893
+ files: activeNotebookContext === null || activeNotebookContext === void 0 ? void 0 : activeNotebookContext.files
6221
6894
  }, null, 2);
6222
6895
  try {
6223
6896
  await navigator.clipboard.writeText(jsonContent);
@@ -6234,8 +6907,8 @@ const ContextManagerSection = ({ contextManager }) => {
6234
6907
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement("button", { className: "button-base", onClick: copyContextManagerToClipboard }, "Copy")),
6235
6908
  refreshKey > 0 && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { className: "settings-option" },
6236
6909
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement("pre", { className: "json-container" }, JSON.stringify({
6237
- variables: contextManager.variables,
6238
- files: contextManager.files
6910
+ variables: activeNotebookContext === null || activeNotebookContext === void 0 ? void 0 : activeNotebookContext.variables,
6911
+ files: activeNotebookContext === null || activeNotebookContext === void 0 ? void 0 : activeNotebookContext.files
6239
6912
  }, null, 2))))));
6240
6913
  };
6241
6914
 
@@ -6516,142 +7189,6 @@ const SupportPage = () => {
6516
7189
  };
6517
7190
 
6518
7191
 
6519
- /***/ }),
6520
-
6521
- /***/ "./lib/Extensions/StreamlitPreview/StreamlitPreviewPlugin.js":
6522
- /*!*******************************************************************!*\
6523
- !*** ./lib/Extensions/StreamlitPreview/StreamlitPreviewPlugin.js ***!
6524
- \*******************************************************************/
6525
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
6526
-
6527
- __webpack_require__.r(__webpack_exports__);
6528
- /* harmony export */ __webpack_require__.d(__webpack_exports__, {
6529
- /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
6530
- /* harmony export */ });
6531
- /* harmony import */ var _jupyterlab_notebook__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @jupyterlab/notebook */ "webpack/sharing/consume/default/@jupyterlab/notebook");
6532
- /* harmony import */ var _jupyterlab_notebook__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_jupyterlab_notebook__WEBPACK_IMPORTED_MODULE_0__);
6533
- /* harmony import */ var _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @jupyterlab/apputils */ "webpack/sharing/consume/default/@jupyterlab/apputils");
6534
- /* harmony import */ var _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_1__);
6535
- /* harmony import */ var _jupyterlab_coreutils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @jupyterlab/coreutils */ "webpack/sharing/consume/default/@jupyterlab/coreutils");
6536
- /* harmony import */ var _jupyterlab_coreutils__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_jupyterlab_coreutils__WEBPACK_IMPORTED_MODULE_2__);
6537
- /* harmony import */ var _lumino_widgets__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @lumino/widgets */ "webpack/sharing/consume/default/@lumino/widgets");
6538
- /* harmony import */ var _lumino_widgets__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_lumino_widgets__WEBPACK_IMPORTED_MODULE_3__);
6539
- /* harmony import */ var _AiChat_token__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../AiChat/token */ "./lib/Extensions/AiChat/token.js");
6540
- /* harmony import */ var _restAPI_RestAPI__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../restAPI/RestAPI */ "./lib/restAPI/RestAPI.js");
6541
- /* harmony import */ var _commands__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../commands */ "./lib/commands.js");
6542
- /*
6543
- * Copyright (c) Saga Inc.
6544
- * Distributed under the terms of the GNU Affero General Public License v3.0 License.
6545
- */
6546
-
6547
-
6548
-
6549
-
6550
-
6551
-
6552
-
6553
-
6554
-
6555
- /**
6556
- * Simple HTML widget for displaying iframe content.
6557
- */
6558
- class IFrameWidget extends _lumino_widgets__WEBPACK_IMPORTED_MODULE_3__.Widget {
6559
- constructor(url) {
6560
- super();
6561
- this.addClass('jp-iframe-widget');
6562
- const iframe = document.createElement('iframe');
6563
- iframe.src = url;
6564
- iframe.style.width = '100%';
6565
- iframe.style.height = '100%';
6566
- iframe.style.border = 'none';
6567
- this.node.appendChild(iframe);
6568
- }
6569
- setUrl(url) {
6570
- const iframe = this.node.querySelector('iframe');
6571
- if (iframe) {
6572
- iframe.src = url;
6573
- }
6574
- }
6575
- }
6576
- /**
6577
- * The streamlit preview plugin.
6578
- */
6579
- const StreamlitPreviewPlugin = {
6580
- id: 'mito-ai:streamlit-preview',
6581
- autoStart: true,
6582
- requires: [_jupyterlab_notebook__WEBPACK_IMPORTED_MODULE_0__.INotebookTracker, _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_1__.ICommandPalette, _AiChat_token__WEBPACK_IMPORTED_MODULE_4__.IChatTracker],
6583
- activate: (app, notebookTracker, palette) => {
6584
- console.log('mito-ai: StreamlitPreviewPlugin activated');
6585
- // Add command to command palette
6586
- app.commands.addCommand(_commands__WEBPACK_IMPORTED_MODULE_5__.previewAsStreamlit, {
6587
- label: 'Preview as Streamlit',
6588
- caption: 'Convert current notebook to Streamlit app and preview it',
6589
- execute: async () => {
6590
- await previewNotebookAsStreamlit(app, notebookTracker);
6591
- }
6592
- });
6593
- // Add to command palette
6594
- palette.addItem({
6595
- command: _commands__WEBPACK_IMPORTED_MODULE_5__.previewAsStreamlit,
6596
- category: 'Mito AI'
6597
- });
6598
- }
6599
- };
6600
- /**
6601
- * Preview the current notebook as a Streamlit app.
6602
- */
6603
- async function previewNotebookAsStreamlit(app, notebookTracker) {
6604
- const notebookPanel = notebookTracker.currentWidget;
6605
- if (!notebookPanel) {
6606
- _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_1__.Notification.error('No notebook is currently active');
6607
- return;
6608
- }
6609
- // First save the notebook to ensure the app is up to date
6610
- await notebookPanel.context.save();
6611
- const notebookPath = notebookPanel.context.path;
6612
- const notebookName = _jupyterlab_coreutils__WEBPACK_IMPORTED_MODULE_2__.PathExt.basename(notebookPath, '.ipynb');
6613
- // Show building notification
6614
- const notificationId = _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_1__.Notification.emit('Building App Preview...', 'in-progress', { autoClose: false });
6615
- try {
6616
- const previewData = await (0,_restAPI_RestAPI__WEBPACK_IMPORTED_MODULE_6__.startStreamlitPreview)(notebookPath);
6617
- // Create iframe widget
6618
- const iframeWidget = new IFrameWidget(previewData.url);
6619
- // Create main area widget
6620
- const widget = new _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_1__.MainAreaWidget({ content: iframeWidget });
6621
- widget.title.label = `App Preview (${notebookName})`;
6622
- widget.title.closable = true;
6623
- // Handle widget disposal
6624
- widget.disposed.connect(() => {
6625
- console.log('Widget disposed, stopping preview');
6626
- void (0,_restAPI_RestAPI__WEBPACK_IMPORTED_MODULE_6__.stopStreamlitPreview)(previewData.id);
6627
- });
6628
- // Add widget to main area with split-right mode
6629
- app.shell.add(widget, 'main', {
6630
- mode: 'split-right',
6631
- ref: notebookPanel.id
6632
- });
6633
- // Update notification to success
6634
- _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_1__.Notification.update({
6635
- id: notificationId,
6636
- message: 'Streamlit preview started successfully!',
6637
- type: 'default',
6638
- autoClose: false
6639
- });
6640
- }
6641
- catch (error) {
6642
- console.error('Error starting streamlit preview:', error);
6643
- // Update notification to error
6644
- _jupyterlab_apputils__WEBPACK_IMPORTED_MODULE_1__.Notification.update({
6645
- id: notificationId,
6646
- message: `Failed to start preview: ${error instanceof Error ? error.message : 'Unknown error'}`,
6647
- type: 'error',
6648
- autoClose: false
6649
- });
6650
- }
6651
- }
6652
- /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (StreamlitPreviewPlugin);
6653
-
6654
-
6655
7192
  /***/ }),
6656
7193
 
6657
7194
  /***/ "./lib/Extensions/ToolbarButtons/ToolbarButtonsPlugin.js":
@@ -6666,12 +7203,10 @@ __webpack_require__.r(__webpack_exports__);
6666
7203
  /* harmony export */ });
6667
7204
  /* harmony import */ var _jupyterlab_notebook__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @jupyterlab/notebook */ "webpack/sharing/consume/default/@jupyterlab/notebook");
6668
7205
  /* harmony import */ var _jupyterlab_notebook__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_jupyterlab_notebook__WEBPACK_IMPORTED_MODULE_0__);
6669
- /* harmony import */ var _commands__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../commands */ "./lib/commands.js");
6670
- /* harmony import */ var _icons__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../icons */ "./lib/icons/index.js");
6671
- /* harmony import */ var _utils_notebook__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../utils/notebook */ "./lib/utils/notebook.js");
6672
- /* harmony import */ var _AppBuilder_NotebookToStreamlit__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../AppBuilder/NotebookToStreamlit */ "./lib/Extensions/AppBuilder/NotebookToStreamlit.js");
6673
- /* harmony import */ var _AppBuilder_AppBuilderPlugin__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../AppBuilder/AppBuilderPlugin */ "./lib/Extensions/AppBuilder/AppBuilderPlugin.js");
6674
- /* harmony import */ var _restAPI_RestAPI__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../restAPI/RestAPI */ "./lib/restAPI/RestAPI.js");
7206
+ /* harmony import */ var _commands__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../commands */ "./lib/commands.js");
7207
+ /* harmony import */ var _icons__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../icons */ "./lib/icons/index.js");
7208
+ /* harmony import */ var _utils_cellMetadata__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../utils/cellMetadata */ "./lib/utils/cellMetadata.js");
7209
+ /* harmony import */ var _restAPI_RestAPI__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../restAPI/RestAPI */ "./lib/restAPI/RestAPI.js");
6675
7210
  /*
6676
7211
  * Copyright (c) Saga Inc.
6677
7212
  * Distributed under the terms of the GNU Affero General Public License v3.0 License.
@@ -6681,8 +7216,6 @@ __webpack_require__.r(__webpack_exports__);
6681
7216
 
6682
7217
 
6683
7218
 
6684
-
6685
-
6686
7219
  const ToolbarButtonsPlugin = {
6687
7220
  // Important: The Cell Toolbar Buttons are added to the toolbar registry via the schema/toolbar-buttons.json file.
6688
7221
  // The id here must be mito-ai:toolbar-buttons otherwise the buttons are not successfully added. My understanding is that
@@ -6691,28 +7224,27 @@ const ToolbarButtonsPlugin = {
6691
7224
  description: 'Adds an "explain code cell with AI" button to the cell toolbar',
6692
7225
  autoStart: true,
6693
7226
  requires: [_jupyterlab_notebook__WEBPACK_IMPORTED_MODULE_0__.INotebookTracker],
6694
- optional: [_AppBuilder_AppBuilderPlugin__WEBPACK_IMPORTED_MODULE_1__.IAppBuilderService],
6695
- activate: (app, notebookTracker, appBuilderService) => {
7227
+ activate: (app, notebookTracker) => {
6696
7228
  const { commands } = app;
6697
7229
  // Important: To add a button to the cell toolbar, the command must start with "toolbar-button:"
6698
7230
  // and the command must match the command in the schema/plugin.json file.
6699
7231
  commands.addCommand('toolbar-button:explain-code', {
6700
- icon: _icons__WEBPACK_IMPORTED_MODULE_2__.lightBulbLabIcon,
7232
+ icon: _icons__WEBPACK_IMPORTED_MODULE_1__.lightBulbLabIcon,
6701
7233
  caption: 'Explain code in AI Chat',
6702
7234
  execute: async () => {
6703
7235
  /*
6704
7236
  In order to click on the cell toolbar button, that cell must be the active cell,
6705
7237
  so the ChatHistoryManager will take care of providing the cell context.
6706
7238
  */
6707
- await app.commands.execute(_commands__WEBPACK_IMPORTED_MODULE_3__.COMMAND_MITO_AI_OPEN_CHAT);
6708
- await app.commands.execute(_commands__WEBPACK_IMPORTED_MODULE_3__.COMMAND_MITO_AI_SEND_EXPLAIN_CODE_MESSAGE);
7239
+ await app.commands.execute(_commands__WEBPACK_IMPORTED_MODULE_2__.COMMAND_MITO_AI_OPEN_CHAT);
7240
+ await app.commands.execute(_commands__WEBPACK_IMPORTED_MODULE_2__.COMMAND_MITO_AI_SEND_EXPLAIN_CODE_MESSAGE);
6709
7241
  },
6710
- isVisible: () => { var _a; return ((_a = notebookTracker.activeCell) === null || _a === void 0 ? void 0 : _a.model.type) === 'code' && app.commands.hasCommand(_commands__WEBPACK_IMPORTED_MODULE_3__.COMMAND_MITO_AI_SEND_EXPLAIN_CODE_MESSAGE); }
7242
+ isVisible: () => { var _a; return ((_a = notebookTracker.activeCell) === null || _a === void 0 ? void 0 : _a.model.type) === 'code' && app.commands.hasCommand(_commands__WEBPACK_IMPORTED_MODULE_2__.COMMAND_MITO_AI_SEND_EXPLAIN_CODE_MESSAGE); }
6711
7243
  });
6712
7244
  commands.addCommand('toolbar-button:toggle-include-cell-in-app', {
6713
7245
  icon: () => {
6714
- const includeCellInApp = (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_4__.getActiveCellIncludeInApp)(notebookTracker);
6715
- return includeCellInApp ? _icons__WEBPACK_IMPORTED_MODULE_2__.AppBuilderIncludeCellLabIcon : _icons__WEBPACK_IMPORTED_MODULE_2__.AppBuilderExcludeCellLabIcon;
7246
+ const includeCellInApp = (0,_utils_cellMetadata__WEBPACK_IMPORTED_MODULE_3__.getActiveCellIncludeInApp)(notebookTracker);
7247
+ return includeCellInApp ? _icons__WEBPACK_IMPORTED_MODULE_1__.AppBuilderIncludeCellLabIcon : _icons__WEBPACK_IMPORTED_MODULE_1__.AppBuilderExcludeCellLabIcon;
6716
7248
  },
6717
7249
  caption: 'Toggle cell output visibility in Streamlit app',
6718
7250
  execute: async () => {
@@ -6729,47 +7261,33 @@ const ToolbarButtonsPlugin = {
6729
7261
  Potential solutions:
6730
7262
  - Use linting (pyright/pylance) to detect reportUnusedExpression in cells that have outputs turned off and remove unused expressions
6731
7263
  - Use AI to identify and remove hanging variables
6732
- - Parse code to find and remove lone variable references and literals
6733
- */
6734
- (0,_utils_notebook__WEBPACK_IMPORTED_MODULE_4__.toggleActiveCellIncludeInAppMetadata)(notebookTracker);
6735
- // Force command refresh to update the icon
6736
- commands.notifyCommandChanged('toolbar-button:toggle-include-cell-in-app');
6737
- },
6738
- isVisible: () => {
6739
- return app.commands.hasCommand(_commands__WEBPACK_IMPORTED_MODULE_3__.COMMAND_MITO_AI_BETA_MODE_ENABLED);
6740
- }
6741
- });
6742
- commands.addCommand('toolbar-button:convert-to-streamlit', {
6743
- label: 'Deploy App',
6744
- caption: 'Convert to Streamlit',
6745
- className: 'text-button-mito-ai button-base button-purple button-small',
6746
- execute: async () => {
6747
- void (0,_AppBuilder_NotebookToStreamlit__WEBPACK_IMPORTED_MODULE_5__.convertNotebookToStreamlit)(notebookTracker, appBuilderService);
7264
+ - Parse code to find and remove lone variable references and literals
7265
+ */
7266
+ (0,_utils_cellMetadata__WEBPACK_IMPORTED_MODULE_3__.toggleActiveCellIncludeInAppMetadata)(notebookTracker);
7267
+ // Force command refresh to update the icon
7268
+ commands.notifyCommandChanged('toolbar-button:toggle-include-cell-in-app');
6748
7269
  },
6749
7270
  isVisible: () => {
6750
- // Default to hidden, will be updated after async check since we are not allowed to
6751
- // use async commands in isVisible.
6752
- return app.commands.hasCommand(_commands__WEBPACK_IMPORTED_MODULE_3__.COMMAND_MITO_AI_BETA_MODE_ENABLED);
7271
+ return app.commands.hasCommand(_commands__WEBPACK_IMPORTED_MODULE_2__.COMMAND_MITO_AI_BETA_MODE_ENABLED);
6753
7272
  }
6754
7273
  });
6755
7274
  commands.addCommand('toolbar-button:preview-as-streamlit', {
6756
- label: 'Preview App',
6757
- caption: 'Preview as Streamlit',
7275
+ label: 'App Mode',
7276
+ caption: 'Preview notebook as app and turn on App Mode',
6758
7277
  className: 'text-button-mito-ai button-base button-purple button-small',
6759
7278
  execute: async () => {
6760
7279
  void app.commands.execute('mito-ai:preview-as-streamlit');
6761
7280
  },
6762
7281
  isVisible: () => {
6763
- return app.commands.hasCommand(_commands__WEBPACK_IMPORTED_MODULE_3__.COMMAND_MITO_AI_BETA_MODE_ENABLED);
7282
+ return app.commands.hasCommand(_commands__WEBPACK_IMPORTED_MODULE_2__.COMMAND_MITO_AI_BETA_MODE_ENABLED);
6764
7283
  }
6765
7284
  });
6766
7285
  // Check if the beta mode is enabled. After checking, tell Jupyter to
6767
7286
  // re-evaluate convert-to-streamlit visibility now that we have had the
6768
7287
  // opportunity to set the mito-ai:beta-mode-enabled command if beta mode is enabled.
6769
- (0,_restAPI_RestAPI__WEBPACK_IMPORTED_MODULE_6__.getSetting)('beta_mode').then(value => {
7288
+ (0,_restAPI_RestAPI__WEBPACK_IMPORTED_MODULE_4__.getSetting)('beta_mode').then(value => {
6770
7289
  if (value === 'true') {
6771
- commands.addCommand(_commands__WEBPACK_IMPORTED_MODULE_3__.COMMAND_MITO_AI_BETA_MODE_ENABLED, { execute: () => { } });
6772
- commands.notifyCommandChanged('toolbar-button:convert-to-streamlit');
7290
+ commands.addCommand(_commands__WEBPACK_IMPORTED_MODULE_2__.COMMAND_MITO_AI_BETA_MODE_ENABLED, { execute: () => { } });
6773
7291
  commands.notifyCommandChanged('toolbar-button:toggle-include-cell-in-app');
6774
7292
  commands.notifyCommandChanged('toolbar-button:preview-as-streamlit');
6775
7293
  }
@@ -7264,13 +7782,13 @@ __webpack_require__.r(__webpack_exports__);
7264
7782
  /* harmony export */ COMMAND_MITO_AI_CELL_TOOLBAR_ACCEPT_CODE: () => (/* binding */ COMMAND_MITO_AI_CELL_TOOLBAR_ACCEPT_CODE),
7265
7783
  /* harmony export */ COMMAND_MITO_AI_CELL_TOOLBAR_REJECT_CODE: () => (/* binding */ COMMAND_MITO_AI_CELL_TOOLBAR_REJECT_CODE),
7266
7784
  /* harmony export */ COMMAND_MITO_AI_OPEN_CHAT: () => (/* binding */ COMMAND_MITO_AI_OPEN_CHAT),
7785
+ /* harmony export */ COMMAND_MITO_AI_PREVIEW_AS_STREAMLIT: () => (/* binding */ COMMAND_MITO_AI_PREVIEW_AS_STREAMLIT),
7267
7786
  /* harmony export */ COMMAND_MITO_AI_PREVIEW_LATEST_CODE: () => (/* binding */ COMMAND_MITO_AI_PREVIEW_LATEST_CODE),
7268
7787
  /* harmony export */ COMMAND_MITO_AI_REJECT_LATEST_CODE: () => (/* binding */ COMMAND_MITO_AI_REJECT_LATEST_CODE),
7269
7788
  /* harmony export */ COMMAND_MITO_AI_SEND_AGENT_MESSAGE: () => (/* binding */ COMMAND_MITO_AI_SEND_AGENT_MESSAGE),
7270
7789
  /* harmony export */ COMMAND_MITO_AI_SEND_DEBUG_ERROR_MESSAGE: () => (/* binding */ COMMAND_MITO_AI_SEND_DEBUG_ERROR_MESSAGE),
7271
7790
  /* harmony export */ COMMAND_MITO_AI_SEND_EXPLAIN_CODE_MESSAGE: () => (/* binding */ COMMAND_MITO_AI_SEND_EXPLAIN_CODE_MESSAGE),
7272
- /* harmony export */ COMMAND_MITO_AI_SEND_MESSAGE: () => (/* binding */ COMMAND_MITO_AI_SEND_MESSAGE),
7273
- /* harmony export */ previewAsStreamlit: () => (/* binding */ previewAsStreamlit)
7791
+ /* harmony export */ COMMAND_MITO_AI_SEND_MESSAGE: () => (/* binding */ COMMAND_MITO_AI_SEND_MESSAGE)
7274
7792
  /* harmony export */ });
7275
7793
  /*
7276
7794
  * Copyright (c) Saga Inc.
@@ -7290,7 +7808,7 @@ const COMMAND_MITO_AI_CELL_TOOLBAR_REJECT_CODE = `toolbar-button:reject-code`;
7290
7808
  // Beta mode commands
7291
7809
  const COMMAND_MITO_AI_BETA_MODE_ENABLED = `${MITO_AI}:beta-mode-enabled`;
7292
7810
  // Streamlit commands
7293
- const previewAsStreamlit = 'mito-ai:preview-as-streamlit';
7811
+ const COMMAND_MITO_AI_PREVIEW_AS_STREAMLIT = 'mito-ai:preview-as-streamlit';
7294
7812
 
7295
7813
 
7296
7814
  /***/ }),
@@ -7972,9 +8490,7 @@ __webpack_require__.r(__webpack_exports__);
7972
8490
 
7973
8491
 
7974
8492
  const MODEL_MAPPINGS = [
7975
- { displayName: _utils_models__WEBPACK_IMPORTED_MODULE_2__.GPT_DISPLAY_NAME, fullName: _utils_models__WEBPACK_IMPORTED_MODULE_2__.GPT_MODEL_NAME },
7976
8493
  { displayName: 'GPT 4.1', fullName: 'gpt-4.1' },
7977
- { displayName: _utils_models__WEBPACK_IMPORTED_MODULE_2__.CLAUDE_OPUS_DISPLAY_NAME, fullName: _utils_models__WEBPACK_IMPORTED_MODULE_2__.CLAUDE_OPUS_MODEL_NAME },
7978
8494
  { displayName: _utils_models__WEBPACK_IMPORTED_MODULE_2__.CLAUDE_SONNET_DISPLAY_NAME, fullName: _utils_models__WEBPACK_IMPORTED_MODULE_2__.CLAUDE_SONNET_MODEL_NAME },
7979
8495
  { displayName: 'Gemini 2.5 Pro', fullName: 'gemini-2.5-pro-preview-03-25' }
7980
8496
  ];
@@ -8886,6 +9402,7 @@ __webpack_require__.r(__webpack_exports__);
8886
9402
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
8887
9403
  /* harmony export */ AppBuilderExcludeCellLabIcon: () => (/* binding */ AppBuilderExcludeCellLabIcon),
8888
9404
  /* harmony export */ AppBuilderIncludeCellLabIcon: () => (/* binding */ AppBuilderIncludeCellLabIcon),
9405
+ /* harmony export */ DeployLabIcon: () => (/* binding */ DeployLabIcon),
8889
9406
  /* harmony export */ NucleusLabIcon: () => (/* binding */ NucleusLabIcon),
8890
9407
  /* harmony export */ OpenIndicatorLabIcon: () => (/* binding */ OpenIndicatorLabIcon),
8891
9408
  /* harmony export */ lightBulbLabIcon: () => (/* binding */ lightBulbLabIcon)
@@ -8897,6 +9414,7 @@ __webpack_require__.r(__webpack_exports__);
8897
9414
  /* harmony import */ var _src_icons_OpenIndicatorIcon_svg__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../src/icons/OpenIndicatorIcon.svg */ "./src/icons/OpenIndicatorIcon.svg");
8898
9415
  /* harmony import */ var _src_icons_AppBuilderExcludeCellIcon_svg__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../src/icons/AppBuilderExcludeCellIcon.svg */ "./src/icons/AppBuilderExcludeCellIcon.svg");
8899
9416
  /* harmony import */ var _src_icons_AppBuilderIncludeCellIcon_svg__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../src/icons/AppBuilderIncludeCellIcon.svg */ "./src/icons/AppBuilderIncludeCellIcon.svg");
9417
+ /* harmony import */ var _src_icons_App_DeployIcon_svg__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../src/icons/App/DeployIcon.svg */ "./src/icons/App/DeployIcon.svg");
8900
9418
  /*
8901
9419
  * Copyright (c) Saga Inc.
8902
9420
  * Distributed under the terms of the GNU Affero General Public License v3.0 License.
@@ -8907,6 +9425,7 @@ __webpack_require__.r(__webpack_exports__);
8907
9425
 
8908
9426
 
8909
9427
 
9428
+
8910
9429
  const lightBulbLabIcon = new _jupyterlab_ui_components__WEBPACK_IMPORTED_MODULE_0__.LabIcon({
8911
9430
  name: 'lightbulb-icon',
8912
9431
  svgstr: _src_icons_LightbulbIcon_svg__WEBPACK_IMPORTED_MODULE_1__
@@ -8927,6 +9446,10 @@ const AppBuilderIncludeCellLabIcon = new _jupyterlab_ui_components__WEBPACK_IMPO
8927
9446
  name: 'app-builder-include-cell-icon',
8928
9447
  svgstr: _src_icons_AppBuilderIncludeCellIcon_svg__WEBPACK_IMPORTED_MODULE_5__
8929
9448
  });
9449
+ const DeployLabIcon = new _jupyterlab_ui_components__WEBPACK_IMPORTED_MODULE_0__.LabIcon({
9450
+ name: 'deploy-icon',
9451
+ svgstr: _src_icons_App_DeployIcon_svg__WEBPACK_IMPORTED_MODULE_6__
9452
+ });
8930
9453
 
8931
9454
 
8932
9455
  /***/ }),
@@ -8945,8 +9468,8 @@ __webpack_require__.r(__webpack_exports__);
8945
9468
  /* harmony import */ var _Extensions_ContextManager_ContextManagerPlugin__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Extensions/ContextManager/ContextManagerPlugin */ "./lib/Extensions/ContextManager/ContextManagerPlugin.js");
8946
9469
  /* harmony import */ var _Extensions_ErrorMimeRenderer_ErrorMimeRendererPlugin__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Extensions/ErrorMimeRenderer/ErrorMimeRendererPlugin */ "./lib/Extensions/ErrorMimeRenderer/ErrorMimeRendererPlugin.js");
8947
9470
  /* harmony import */ var _Extensions_ToolbarButtons_ToolbarButtonsPlugin__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./Extensions/ToolbarButtons/ToolbarButtonsPlugin */ "./lib/Extensions/ToolbarButtons/ToolbarButtonsPlugin.js");
8948
- /* harmony import */ var _Extensions_AppBuilder_AppBuilderPlugin__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Extensions/AppBuilder/AppBuilderPlugin */ "./lib/Extensions/AppBuilder/AppBuilderPlugin.js");
8949
- /* harmony import */ var _Extensions_StreamlitPreview_StreamlitPreviewPlugin__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./Extensions/StreamlitPreview/StreamlitPreviewPlugin */ "./lib/Extensions/StreamlitPreview/StreamlitPreviewPlugin.js");
9471
+ /* harmony import */ var _Extensions_AppDeploy_AppDeployPlugin__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Extensions/AppDeploy/AppDeployPlugin */ "./lib/Extensions/AppDeploy/AppDeployPlugin.js");
9472
+ /* harmony import */ var _Extensions_AppPreview_StreamlitPreviewPlugin__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./Extensions/AppPreview/StreamlitPreviewPlugin */ "./lib/Extensions/AppPreview/StreamlitPreviewPlugin.js");
8950
9473
  /* harmony import */ var _Extensions_emptyCell_EmptyCellPlugin__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./Extensions/emptyCell/EmptyCellPlugin */ "./lib/Extensions/emptyCell/EmptyCellPlugin.js");
8951
9474
  /* harmony import */ var _Extensions_status__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./Extensions/status */ "./lib/Extensions/status/index.js");
8952
9475
  /* harmony import */ var _Extensions_SettingsManager_SettingsManagerPlugin__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./Extensions/SettingsManager/SettingsManagerPlugin */ "./lib/Extensions/SettingsManager/SettingsManagerPlugin.js");
@@ -8975,8 +9498,8 @@ __webpack_require__.r(__webpack_exports__);
8975
9498
  _Extensions_AiChat_AiChatPlugin__WEBPACK_IMPORTED_MODULE_0__["default"],
8976
9499
  _Extensions_ErrorMimeRenderer_ErrorMimeRendererPlugin__WEBPACK_IMPORTED_MODULE_1__["default"],
8977
9500
  _Extensions_ContextManager_ContextManagerPlugin__WEBPACK_IMPORTED_MODULE_2__["default"],
8978
- _Extensions_AppBuilder_AppBuilderPlugin__WEBPACK_IMPORTED_MODULE_3__["default"],
8979
- _Extensions_StreamlitPreview_StreamlitPreviewPlugin__WEBPACK_IMPORTED_MODULE_4__["default"],
9501
+ _Extensions_AppDeploy_AppDeployPlugin__WEBPACK_IMPORTED_MODULE_3__["default"],
9502
+ _Extensions_AppPreview_StreamlitPreviewPlugin__WEBPACK_IMPORTED_MODULE_4__["default"],
8980
9503
  _Extensions_ToolbarButtons_ToolbarButtonsPlugin__WEBPACK_IMPORTED_MODULE_5__["default"],
8981
9504
  _Extensions_emptyCell_EmptyCellPlugin__WEBPACK_IMPORTED_MODULE_6__.emptyCellPlaceholder,
8982
9505
  _Extensions_status__WEBPACK_IMPORTED_MODULE_7__.statusItem,
@@ -9100,10 +9623,10 @@ const getDatabaseConnections = async () => {
9100
9623
  STREAMLIT PREVIEW ENDPOINTS
9101
9624
 
9102
9625
  ************************************/
9103
- const startStreamlitPreview = async (notebookPath) => {
9626
+ const startStreamlitPreview = async (notebookPath, force_recreate = false) => {
9104
9627
  const response = await (0,_utils__WEBPACK_IMPORTED_MODULE_0__.requestAPI)('streamlit-preview', {
9105
9628
  method: 'POST',
9106
- body: JSON.stringify({ notebook_path: notebookPath }),
9629
+ body: JSON.stringify({ notebook_path: notebookPath, force_recreate: force_recreate }),
9107
9630
  });
9108
9631
  if (response.error) {
9109
9632
  throw new Error(response.error.message);
@@ -9227,13 +9750,14 @@ const getXsrfToken = () => {
9227
9750
  __webpack_require__.r(__webpack_exports__);
9228
9751
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
9229
9752
  /* harmony export */ acceptAndRunCellUpdate: () => (/* binding */ acceptAndRunCellUpdate),
9230
- /* harmony export */ acceptAndRunCode: () => (/* binding */ acceptAndRunCode),
9231
9753
  /* harmony export */ retryIfExecutionError: () => (/* binding */ retryIfExecutionError),
9232
9754
  /* harmony export */ runAllCells: () => (/* binding */ runAllCells)
9233
9755
  /* harmony export */ });
9234
- /* harmony import */ var _Extensions_ErrorMimeRenderer_errorUtils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../Extensions/ErrorMimeRenderer/errorUtils */ "./lib/Extensions/ErrorMimeRenderer/errorUtils.js");
9235
- /* harmony import */ var _sleep__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./sleep */ "./lib/utils/sleep.js");
9236
- /* harmony import */ var _notebook__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./notebook */ "./lib/utils/notebook.js");
9756
+ /* harmony import */ var _jupyterlab_notebook__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @jupyterlab/notebook */ "webpack/sharing/consume/default/@jupyterlab/notebook");
9757
+ /* harmony import */ var _jupyterlab_notebook__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_jupyterlab_notebook__WEBPACK_IMPORTED_MODULE_0__);
9758
+ /* harmony import */ var _Extensions_ErrorMimeRenderer_errorUtils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../Extensions/ErrorMimeRenderer/errorUtils */ "./lib/Extensions/ErrorMimeRenderer/errorUtils.js");
9759
+ /* harmony import */ var _sleep__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./sleep */ "./lib/utils/sleep.js");
9760
+ /* harmony import */ var _notebook__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./notebook */ "./lib/utils/notebook.js");
9237
9761
  /*
9238
9762
  * Copyright (c) Saga Inc.
9239
9763
  * Distributed under the terms of the GNU Affero General Public License v3.0 License.
@@ -9241,70 +9765,71 @@ __webpack_require__.r(__webpack_exports__);
9241
9765
 
9242
9766
 
9243
9767
 
9244
- const acceptAndRunCellUpdate = async (cellUpdate, notebookTracker, app, previewAICodeToActiveCell, acceptAICode) => {
9768
+
9769
+
9770
+ const acceptAndRunCellUpdate = async (cellUpdate, notebookPanel) => {
9245
9771
  // If the cellUpdate is creating a new code cell, insert it
9246
- // before previewing and accepting the code.
9772
+ // before previewing and accepting the code. It is safe to do this
9773
+ // in the background agent because it does not effect the active cell
9774
+ // in other notebooks.
9247
9775
  if (cellUpdate.type === 'new') {
9248
9776
  // makes the cell the active cell
9249
- (0,_notebook__WEBPACK_IMPORTED_MODULE_0__.createCodeCellAtIndexAndActivate)(notebookTracker, cellUpdate.index);
9777
+ (0,_notebook__WEBPACK_IMPORTED_MODULE_1__.createCodeCellAtIndexAndActivate)(notebookPanel, cellUpdate.index);
9250
9778
  }
9251
9779
  else {
9252
- (0,_notebook__WEBPACK_IMPORTED_MODULE_0__.setActiveCellByID)(notebookTracker, cellUpdate.id);
9780
+ (0,_notebook__WEBPACK_IMPORTED_MODULE_1__.setActiveCellByIDInNotebookPanel)(notebookPanel, cellUpdate.id);
9253
9781
  }
9254
- // The target cell should now be the active cell
9255
- await acceptAndRunCode(app, notebookTracker, previewAICodeToActiveCell, acceptAICode, cellUpdate.cell_type);
9256
- };
9257
- const acceptAndRunCode = async (app, notebookTracker, previewAICodeToActiveCell, acceptAICode, cellType) => {
9258
- /*
9259
- PreviewAICode applies the code to the current active code cell,
9260
- so make sure that correct cell is active before calling
9261
- this function
9262
- */
9263
- previewAICodeToActiveCell();
9264
- acceptAICode();
9782
+ const notebook = notebookPanel.content;
9783
+ const context = notebookPanel.context;
9784
+ if (notebook === undefined) {
9785
+ return;
9786
+ }
9787
+ const cellID = (0,_notebook__WEBPACK_IMPORTED_MODULE_1__.getActiveCellIDInNotebookPanel)(notebookPanel);
9788
+ (0,_notebook__WEBPACK_IMPORTED_MODULE_1__.writeCodeToCellByIDInNotebookPanel)(notebookPanel, cellUpdate.code, cellID);
9265
9789
  // We always create code cells, and then convert to markdown if necessary.
9266
- if (cellType === 'markdown') {
9267
- await app.commands.execute("notebook:change-cell-to-markdown");
9790
+ if (cellUpdate.cell_type === 'markdown') {
9791
+ _jupyterlab_notebook__WEBPACK_IMPORTED_MODULE_0__.NotebookActions.changeCellType(notebook, 'markdown');
9268
9792
  }
9269
- else if (cellType === 'code') {
9270
- await app.commands.execute("notebook:change-cell-to-code");
9793
+ else if (cellUpdate.cell_type === 'code') {
9794
+ _jupyterlab_notebook__WEBPACK_IMPORTED_MODULE_0__.NotebookActions.changeCellType(notebook, 'code');
9271
9795
  }
9272
9796
  // This awaits until after the execution is finished.
9273
9797
  // Note that it is important that we just run the cell and don't run and advance the cell.
9274
9798
  // We rely on the active cell remaining the same after running the cell in order to get the output
9275
9799
  // of the cell to send to the agent. This is changeable in the future, but for now its an invariant we rely on.
9276
- await app.commands.execute("notebook:run-cell");
9800
+ await _jupyterlab_notebook__WEBPACK_IMPORTED_MODULE_0__.NotebookActions.run(notebook, context === null || context === void 0 ? void 0 : context.sessionContext);
9277
9801
  // Scroll to the bottom of the active cell to show the output
9278
- const activeCellID = (0,_notebook__WEBPACK_IMPORTED_MODULE_0__.getActiveCellID)(notebookTracker);
9802
+ // as long as we are not operating in background agent mode.
9803
+ const activeCellID = (0,_notebook__WEBPACK_IMPORTED_MODULE_1__.getActiveCellIDInNotebookPanel)(notebookPanel);
9279
9804
  if (activeCellID) {
9280
- (0,_notebook__WEBPACK_IMPORTED_MODULE_0__.scrollToCell)(notebookTracker, activeCellID, undefined, 'end');
9805
+ (0,_notebook__WEBPACK_IMPORTED_MODULE_1__.scrollToCell)(notebookPanel, activeCellID, undefined, 'end');
9281
9806
  }
9282
9807
  // By sleeping here, we make sure that this function returns after the variable manager
9283
9808
  // has updated the state of the variables. This ensures that on the next Ai message
9284
9809
  // gets the most up to date data.
9285
- await (0,_sleep__WEBPACK_IMPORTED_MODULE_1__.sleep)(1000);
9810
+ await (0,_sleep__WEBPACK_IMPORTED_MODULE_2__.sleep)(1000);
9286
9811
  };
9287
- const retryIfExecutionError = async (notebookTracker, app, getDuplicateChatHistoryManager, addAIMessageFromResponseAndUpdateState, sendAgentSmartDebugMessage, previewAICodeToActiveCell, acceptAICode, shouldContinueAgentExecution, finalizeAgentStop, chatHistoryManagerRef) => {
9288
- var _a, _b, _c;
9289
- const cell = (_b = (_a = notebookTracker.currentWidget) === null || _a === void 0 ? void 0 : _a.content) === null || _b === void 0 ? void 0 : _b.activeCell;
9812
+ const retryIfExecutionError = async (notebookPanel, app, sendAgentSmartDebugMessage, shouldContinueAgentExecution, markAgentForStopping, chatHistoryManagerRef) => {
9813
+ var _a;
9814
+ const cell = notebookPanel.content.activeCell;
9290
9815
  // Note: If you update the max retries, update the message we display on each failure
9291
9816
  // attempt to ensure we don't say "third attempt" over and over again.
9292
9817
  const MAX_RETRIES = 3;
9293
9818
  let attempts = 0;
9294
9819
  let runAllCellsAttempts = 0;
9295
9820
  const MAX_RUN_ALL_CELLS_ATTEMPTS = 2; // Only allow two run_all_cells attempt per error cycle
9296
- while ((0,_notebook__WEBPACK_IMPORTED_MODULE_0__.didCellExecutionError)(cell) && attempts < MAX_RETRIES) {
9821
+ while ((0,_notebook__WEBPACK_IMPORTED_MODULE_1__.didCellExecutionError)(cell) && attempts < MAX_RETRIES) {
9297
9822
  if (!shouldContinueAgentExecution.current) {
9298
- finalizeAgentStop();
9823
+ await markAgentForStopping();
9299
9824
  return 'interupted';
9300
9825
  }
9301
9826
  // If the code cell has an error, we need to send the error to the AI
9302
9827
  // and get it to fix the error.
9303
- const errorOutput = (_c = cell === null || cell === void 0 ? void 0 : cell.model.outputs) === null || _c === void 0 ? void 0 : _c.toJSON().find(output => output.output_type === "error");
9828
+ const errorOutput = (_a = cell === null || cell === void 0 ? void 0 : cell.model.outputs) === null || _a === void 0 ? void 0 : _a.toJSON().find(output => output.output_type === "error");
9304
9829
  if (!errorOutput) {
9305
9830
  return 'success'; // If no error output, we're done
9306
9831
  }
9307
- const errorMessage = (0,_Extensions_ErrorMimeRenderer_errorUtils__WEBPACK_IMPORTED_MODULE_2__.getFullErrorMessageFromTraceback)(errorOutput.traceback);
9832
+ const errorMessage = (0,_Extensions_ErrorMimeRenderer_errorUtils__WEBPACK_IMPORTED_MODULE_3__.getFullErrorMessageFromTraceback)(errorOutput.traceback);
9308
9833
  await sendAgentSmartDebugMessage(errorMessage);
9309
9834
  const aiDisplayOptimizedChatItem = chatHistoryManagerRef.current.getLastAIDisplayOptimizedChatItem();
9310
9835
  // Handle different response types from the agent when fixing errors
@@ -9315,7 +9840,7 @@ const retryIfExecutionError = async (notebookTracker, app, getDuplicateChatHisto
9315
9840
  if (agentResponse.type === 'cell_update') {
9316
9841
  const cellUpdate = agentResponse.cell_update;
9317
9842
  if (cellUpdate !== undefined && cellUpdate !== null) {
9318
- await acceptAndRunCellUpdate(cellUpdate, notebookTracker, app, previewAICodeToActiveCell, acceptAICode);
9843
+ await acceptAndRunCellUpdate(cellUpdate, notebookPanel);
9319
9844
  }
9320
9845
  }
9321
9846
  else if (agentResponse.type === 'run_all_cells') {
@@ -9326,7 +9851,7 @@ const retryIfExecutionError = async (notebookTracker, app, getDuplicateChatHisto
9326
9851
  }
9327
9852
  runAllCellsAttempts++;
9328
9853
  // Execute runAllCells to fix NameError issues
9329
- const result = await runAllCells(app, notebookTracker);
9854
+ const result = await runAllCells(app, notebookPanel);
9330
9855
  if (!result.success) {
9331
9856
  // If run_all_cells resulted in an error, we should continue with error handling
9332
9857
  // The error will be caught in the main loop
@@ -9339,32 +9864,29 @@ const retryIfExecutionError = async (notebookTracker, app, getDuplicateChatHisto
9339
9864
  }
9340
9865
  attempts++;
9341
9866
  // If this was the last attempt and it still failed
9342
- if (attempts === MAX_RETRIES && (0,_notebook__WEBPACK_IMPORTED_MODULE_0__.didCellExecutionError)(cell)) {
9867
+ if (attempts === MAX_RETRIES && (0,_notebook__WEBPACK_IMPORTED_MODULE_1__.didCellExecutionError)(cell)) {
9343
9868
  return 'failure';
9344
9869
  }
9345
9870
  }
9346
9871
  return 'success';
9347
9872
  };
9348
- const runAllCells = async (app, notebookTracker) => {
9873
+ const runAllCells = async (app, notebookPanel) => {
9349
9874
  var _a, _b;
9350
- await app.commands.execute("notebook:run-all-cells");
9875
+ const notebook = notebookPanel.content;
9876
+ const sessionContext = (_a = notebookPanel.context) === null || _a === void 0 ? void 0 : _a.sessionContext;
9877
+ await _jupyterlab_notebook__WEBPACK_IMPORTED_MODULE_0__.NotebookActions.runAll(notebook, sessionContext);
9351
9878
  // Give the execution some time to complete and update variables
9352
9879
  // This ensures that the variable manager has time to update the state
9353
- await (0,_sleep__WEBPACK_IMPORTED_MODULE_1__.sleep)(2000);
9354
- // Check all cells for errors after execution
9355
- const notebook = (_a = notebookTracker.currentWidget) === null || _a === void 0 ? void 0 : _a.content;
9356
- if (!notebook) {
9357
- return { success: false, errorMessage: "No active notebook found" };
9358
- }
9880
+ await (0,_sleep__WEBPACK_IMPORTED_MODULE_2__.sleep)(2000);
9359
9881
  // Iterate through all cells to find any with errors
9360
9882
  for (let i = 0; i < notebook.widgets.length; i++) {
9361
9883
  const cell = notebook.widgets[i];
9362
9884
  if (cell && cell.model.type === 'code') {
9363
9885
  const codeCell = cell;
9364
- if ((0,_notebook__WEBPACK_IMPORTED_MODULE_0__.didCellExecutionError)(codeCell)) {
9886
+ if ((0,_notebook__WEBPACK_IMPORTED_MODULE_1__.didCellExecutionError)(codeCell)) {
9365
9887
  const errorOutput = (_b = codeCell.model.outputs) === null || _b === void 0 ? void 0 : _b.toJSON().find(output => output.output_type === "error");
9366
9888
  if (errorOutput) {
9367
- const errorMessage = (0,_Extensions_ErrorMimeRenderer_errorUtils__WEBPACK_IMPORTED_MODULE_2__.getFullErrorMessageFromTraceback)(errorOutput.traceback);
9889
+ const errorMessage = (0,_Extensions_ErrorMimeRenderer_errorUtils__WEBPACK_IMPORTED_MODULE_3__.getFullErrorMessageFromTraceback)(errorOutput.traceback);
9368
9890
  return {
9369
9891
  success: false,
9370
9892
  errorMessage: errorMessage,
@@ -9507,6 +10029,146 @@ const checkForBlacklistedWords = (code) => {
9507
10029
  };
9508
10030
 
9509
10031
 
10032
+ /***/ }),
10033
+
10034
+ /***/ "./lib/utils/cellMetadata.js":
10035
+ /*!***********************************!*\
10036
+ !*** ./lib/utils/cellMetadata.js ***!
10037
+ \***********************************/
10038
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
10039
+
10040
+ __webpack_require__.r(__webpack_exports__);
10041
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
10042
+ /* harmony export */ getActiveCellIncludeInApp: () => (/* binding */ getActiveCellIncludeInApp),
10043
+ /* harmony export */ getIncludeCellInApp: () => (/* binding */ getIncludeCellInApp),
10044
+ /* harmony export */ toggleActiveCellIncludeInAppMetadata: () => (/* binding */ toggleActiveCellIncludeInAppMetadata),
10045
+ /* harmony export */ toggleIncludeCellInAppMetadata: () => (/* binding */ toggleIncludeCellInAppMetadata)
10046
+ /* harmony export */ });
10047
+ /* harmony import */ var _notebook__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./notebook */ "./lib/utils/notebook.js");
10048
+ /*
10049
+ * Copyright (c) Saga Inc.
10050
+ * Distributed under the terms of the GNU Affero General Public License v3.0 License.
10051
+ */
10052
+
10053
+ const INCLUDE_CELL_IN_APP = 'include-cell-in-app';
10054
+ const toggleActiveCellIncludeInAppMetadata = (notebookTracker) => {
10055
+ const activeCellID = (0,_notebook__WEBPACK_IMPORTED_MODULE_0__.getActiveCellID)(notebookTracker);
10056
+ toggleIncludeCellInAppMetadata(notebookTracker, activeCellID);
10057
+ };
10058
+ const toggleIncludeCellInAppMetadata = (notebookTracker, cellID) => {
10059
+ if (cellID === undefined) {
10060
+ return;
10061
+ }
10062
+ const cell = (0,_notebook__WEBPACK_IMPORTED_MODULE_0__.getCellByID)(notebookTracker, cellID);
10063
+ if (!cell) {
10064
+ return undefined;
10065
+ }
10066
+ if (Object.prototype.hasOwnProperty.call(cell.model.metadata, INCLUDE_CELL_IN_APP)) {
10067
+ const originalVisibility = cell.model.getMetadata(INCLUDE_CELL_IN_APP);
10068
+ cell.model.setMetadata(INCLUDE_CELL_IN_APP, !originalVisibility);
10069
+ }
10070
+ else {
10071
+ // If the metadata doesn't exist yet, that means the user has not yet toggled the visibility.
10072
+ // The default value is to show the output, so the first toggle should set the visibiltiy to false.
10073
+ cell.model.setMetadata(INCLUDE_CELL_IN_APP, false);
10074
+ }
10075
+ };
10076
+ const getActiveCellIncludeInApp = (notebookTracker) => {
10077
+ const activeCellID = (0,_notebook__WEBPACK_IMPORTED_MODULE_0__.getActiveCellID)(notebookTracker);
10078
+ return getIncludeCellInApp(notebookTracker, activeCellID);
10079
+ };
10080
+ const getIncludeCellInApp = (notebookTracker, cellID) => {
10081
+ /*
10082
+ Checks the cell metadata tag to see if the user has marked that this cell should not be included in the app.
10083
+ */
10084
+ const cell = (0,_notebook__WEBPACK_IMPORTED_MODULE_0__.getCellByID)(notebookTracker, cellID);
10085
+ if (!cell) {
10086
+ return false;
10087
+ }
10088
+ if (!Object.prototype.hasOwnProperty.call(cell.model.metadata, INCLUDE_CELL_IN_APP)) {
10089
+ cell.model.setMetadata(INCLUDE_CELL_IN_APP, true);
10090
+ }
10091
+ return cell.model.getMetadata(INCLUDE_CELL_IN_APP);
10092
+ };
10093
+
10094
+
10095
+ /***/ }),
10096
+
10097
+ /***/ "./lib/utils/cellOutput.js":
10098
+ /*!*********************************!*\
10099
+ !*** ./lib/utils/cellOutput.js ***!
10100
+ \*********************************/
10101
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
10102
+
10103
+ __webpack_require__.r(__webpack_exports__);
10104
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
10105
+ /* harmony export */ getActiveCellOutput: () => (/* binding */ getActiveCellOutput),
10106
+ /* harmony export */ getCellOutputByID: () => (/* binding */ getCellOutputByID),
10107
+ /* harmony export */ getCellOutputByIDInNotebook: () => (/* binding */ getCellOutputByIDInNotebook)
10108
+ /* harmony export */ });
10109
+ /* harmony import */ var _jupyterlab_cells__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @jupyterlab/cells */ "webpack/sharing/consume/default/@jupyterlab/cells");
10110
+ /* harmony import */ var _jupyterlab_cells__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_jupyterlab_cells__WEBPACK_IMPORTED_MODULE_0__);
10111
+ /* harmony import */ var _notebook__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./notebook */ "./lib/utils/notebook.js");
10112
+ /*
10113
+ * Copyright (c) Saga Inc.
10114
+ * Distributed under the terms of the GNU Affero General Public License v3.0 License.
10115
+ */
10116
+
10117
+
10118
+ const getActiveCellOutput = async (notebookTracker) => {
10119
+ const activeCellID = (0,_notebook__WEBPACK_IMPORTED_MODULE_1__.getActiveCellID)(notebookTracker);
10120
+ return getCellOutputByID(notebookTracker, activeCellID);
10121
+ };
10122
+ const getCellOutputByID = async (notebookTracker, codeCellID) => {
10123
+ const notebookPanel = notebookTracker.currentWidget;
10124
+ return getCellOutputByIDInNotebook(notebookPanel, codeCellID);
10125
+ };
10126
+ const getCellOutputByIDInNotebook = async (notebookPanel, codeCellID) => {
10127
+ // TODO: There is a bug where if the cell is not actually rendered on the screen,
10128
+ // then the output is not captured. This is pretty unlikely to happen currently because
10129
+ // the agent scrolls to the cell.
10130
+ var _a;
10131
+ if (codeCellID === undefined || notebookPanel === null) {
10132
+ return undefined;
10133
+ }
10134
+ const cell = notebookPanel.content.widgets.find(cell => cell.model.id === codeCellID);
10135
+ if (!(cell instanceof _jupyterlab_cells__WEBPACK_IMPORTED_MODULE_0__.CodeCell)) {
10136
+ return undefined;
10137
+ }
10138
+ const outputNode = (_a = cell.outputArea) === null || _a === void 0 ? void 0 : _a.node;
10139
+ if (!outputNode)
10140
+ return undefined;
10141
+ // Find the top-level Jupyter image output div
10142
+ // so we can check if there is a base64 encoded image
10143
+ // already constructed for us.
10144
+ const renderedImageDiv = outputNode.querySelector('.jp-RenderedImage.jp-OutputArea-output');
10145
+ // If the image is the top-level output, then just use that instead
10146
+ // of capturing the entire output node. This is much faster and handles
10147
+ // matplotlib graphs.
10148
+ if (renderedImageDiv) {
10149
+ const img = renderedImageDiv.querySelector('img');
10150
+ if (img && img.src.startsWith('data:image')) {
10151
+ console.log('image found in top-level output');
10152
+ // Remove the data URL prefix
10153
+ // The img is initially in the format data:image/png;base64, <base64_data>
10154
+ // We want to return the base64 data.
10155
+ const base64 = img.src.split(',')[1];
10156
+ return base64;
10157
+ }
10158
+ }
10159
+ // Fallback: (optional) handle other output types, or use captureNode if needed
10160
+ // Previously, we used html2canvas to capture the entire output node. This would
10161
+ // give us the output even if it was html, svg, text, etc. However, starting around
10162
+ // Chrome release 138, html2canvas became untenably slow. https://issues.chromium.org/issues/429073017
10163
+ if (outputNode) {
10164
+ // If the AI requested, a cell output that we cannot provide, we just tell it
10165
+ // "Cell Output is present in notebook, but not available to share with the AI right now"
10166
+ return "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rNkrAoqAIqAIKAKKgCKgCCgCioAioAgoAoqAIqAIKAKKgCKgjliVAUVAEVAEFAFFQBFQBBQBRUARUAQUAUVAEVAEFAFFQBFQBJqMwHDjiP3888+jUPXq1cuMPPLI0TB5+NNPP5mff/5Zfrprz549zfjjj+9+640ioAgoAoqAItAKBP7++28zbNiwpKgxxhijFUWWWsZvv/1murq6TI8ePcxoo41Wat7NzKy7495MbDTv4ROBIvZzEUTKaGvt4r1IvUf0tL/++msCAf0C/YPS8I+A2AOMx0cdddRuVeHuzHu3Ano4YlZ13HD0MptclaY5YocOHWpef/118+qrrxruJ5tsMjP11FObxRZbzIwyyiilVuubb74xvXv3juZ5xRVXmEUWWSQaJg+POOIIc9FFF8lPd11ooYXM1Vdf7X43++aLL74wL7/8snnllVfMOOOMY+aee24zxxxzmO44CG82Vp2Y//TTT5+wtdlmm5n+/ft3IovKkyLgENhuu+3Mvffem+jlBx54wD3Xm85A4PLLLzf9+vVLmBk8eLCZccYZO4OxBrmg//z222+Tfuymm25qMFX7o3V33NuPoHLQbgReeukls/baaydsDBo0yKyxxhqpLBW1n1MzbiCgaFtrJ+8NVE+jRBB47733zPLLL5+EHH744aZPnz6RWPqoVQi0atwi9sBKK61kzjzzzFZVr5RyujPvPgA4lPHLCPHuxxtvPPlZdf3hhx/Mu+++W/U89mDKKac0E088cSyoY55l6ReLMK06rgh6I17a0h2xzALsv//+5vbbb4+iOeaYY5oTTjjBrLjiitHwPA+/++47s+CCC0aTNuKIHTBggLnggguq0rfKEcuqgEMOOcRceeWVVTzw4PzzzzfLLLNMNKyshy+++KIZMmRIkt1WW21lJpxwwrKybno+ncK7GDQbbrihGThwYNPrrQV0TwQ6RV633nprgwN20kknNY899lj3BLOFXN92223mjTfeMKOPPrrp27dv00u+7LLLkn6Bgu6++24z00wzNb3MMguQwQsTit3JEdspuGPXiF2ywgormHnmmafM19PRebW6rXU0GDmYe/755816662XpDzxxBOdUzaWVVH7OZZno8+KtrV28t5oHRuJNyLJu++kOOyww8wWW2zRCEQap0kI5Bm35JHXueaay/zyyy+m3Y7Y7sx7URG48847K2zX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";
10167
+ }
10168
+ return undefined;
10169
+ };
10170
+
10171
+
9510
10172
  /***/ }),
9511
10173
 
9512
10174
  /***/ "./lib/utils/chatHistory.js":
@@ -9994,23 +10656,19 @@ const stripFileEnding = (rule) => {
9994
10656
 
9995
10657
  __webpack_require__.r(__webpack_exports__);
9996
10658
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
9997
- /* harmony export */ CLAUDE_OPUS_DISPLAY_NAME: () => (/* binding */ CLAUDE_OPUS_DISPLAY_NAME),
9998
- /* harmony export */ CLAUDE_OPUS_MODEL_NAME: () => (/* binding */ CLAUDE_OPUS_MODEL_NAME),
9999
10659
  /* harmony export */ CLAUDE_SONNET_DISPLAY_NAME: () => (/* binding */ CLAUDE_SONNET_DISPLAY_NAME),
10000
10660
  /* harmony export */ CLAUDE_SONNET_MODEL_NAME: () => (/* binding */ CLAUDE_SONNET_MODEL_NAME),
10001
- /* harmony export */ GPT_DISPLAY_NAME: () => (/* binding */ GPT_DISPLAY_NAME),
10002
- /* harmony export */ GPT_MODEL_NAME: () => (/* binding */ GPT_MODEL_NAME)
10661
+ /* harmony export */ GPT_4_1_DISPLAY_NAME: () => (/* binding */ GPT_4_1_DISPLAY_NAME),
10662
+ /* harmony export */ GPT_4_1_MODEL_NAME: () => (/* binding */ GPT_4_1_MODEL_NAME)
10003
10663
  /* harmony export */ });
10004
10664
  /*
10005
10665
  * Copyright (c) Saga Inc.
10006
10666
  * Distributed under the terms of the GNU Affero General Public License v3.0 License.
10007
10667
  */
10008
- const CLAUDE_OPUS_DISPLAY_NAME = 'Claude 4.1 Opus';
10009
- const CLAUDE_OPUS_MODEL_NAME = 'claude-opus-4-1-20250805';
10010
- const CLAUDE_SONNET_DISPLAY_NAME = 'Claude 4 Sonnet';
10011
- const CLAUDE_SONNET_MODEL_NAME = 'claude-sonnet-4-20250514';
10012
- const GPT_DISPLAY_NAME = 'GPT 5 (max)';
10013
- const GPT_MODEL_NAME = 'gpt-5';
10668
+ const CLAUDE_SONNET_DISPLAY_NAME = 'Claude 4.5 Sonnet';
10669
+ const CLAUDE_SONNET_MODEL_NAME = 'claude-sonnet-4-5-20250929';
10670
+ const GPT_4_1_DISPLAY_NAME = 'GPT 4.1';
10671
+ const GPT_4_1_MODEL_NAME = 'gpt-4.1';
10014
10672
 
10015
10673
 
10016
10674
  /***/ }),
@@ -10026,156 +10684,82 @@ __webpack_require__.r(__webpack_exports__);
10026
10684
  /* harmony export */ createCodeCellAtIndexAndActivate: () => (/* binding */ createCodeCellAtIndexAndActivate),
10027
10685
  /* harmony export */ didCellExecutionError: () => (/* binding */ didCellExecutionError),
10028
10686
  /* harmony export */ getAIOptimizedCells: () => (/* binding */ getAIOptimizedCells),
10687
+ /* harmony export */ getAIOptimizedCellsInNotebookPanel: () => (/* binding */ getAIOptimizedCellsInNotebookPanel),
10029
10688
  /* harmony export */ getActiveCell: () => (/* binding */ getActiveCell),
10030
10689
  /* harmony export */ getActiveCellCode: () => (/* binding */ getActiveCellCode),
10031
10690
  /* harmony export */ getActiveCellID: () => (/* binding */ getActiveCellID),
10032
- /* harmony export */ getActiveCellIncludeInApp: () => (/* binding */ getActiveCellIncludeInApp),
10033
- /* harmony export */ getActiveCellOutput: () => (/* binding */ getActiveCellOutput),
10691
+ /* harmony export */ getActiveCellIDInNotebookPanel: () => (/* binding */ getActiveCellIDInNotebookPanel),
10692
+ /* harmony export */ getActiveCellInNotebookPanel: () => (/* binding */ getActiveCellInNotebookPanel),
10034
10693
  /* harmony export */ getCellByID: () => (/* binding */ getCellByID),
10694
+ /* harmony export */ getCellByIDInNotebookPanel: () => (/* binding */ getCellByIDInNotebookPanel),
10035
10695
  /* harmony export */ getCellCodeByID: () => (/* binding */ getCellCodeByID),
10696
+ /* harmony export */ getCellCodeByIDInNotebookPanel: () => (/* binding */ getCellCodeByIDInNotebookPanel),
10036
10697
  /* harmony export */ getCellIndexByID: () => (/* binding */ getCellIndexByID),
10037
- /* harmony export */ getCellOutputByID: () => (/* binding */ getCellOutputByID),
10038
- /* harmony export */ getIncludeCellInApp: () => (/* binding */ getIncludeCellInApp),
10698
+ /* harmony export */ getCellIndexByIDInNotebookPanel: () => (/* binding */ getCellIndexByIDInNotebookPanel),
10039
10699
  /* harmony export */ getNotebookName: () => (/* binding */ getNotebookName),
10040
10700
  /* harmony export */ highlightCodeCell: () => (/* binding */ highlightCodeCell),
10041
10701
  /* harmony export */ highlightLinesOfCodeInCodeCell: () => (/* binding */ highlightLinesOfCodeInCodeCell),
10042
10702
  /* harmony export */ scrollToAndHighlightCell: () => (/* binding */ scrollToAndHighlightCell),
10043
10703
  /* harmony export */ scrollToCell: () => (/* binding */ scrollToCell),
10044
10704
  /* harmony export */ setActiveCellByID: () => (/* binding */ setActiveCellByID),
10045
- /* harmony export */ toggleActiveCellIncludeInAppMetadata: () => (/* binding */ toggleActiveCellIncludeInAppMetadata),
10046
- /* harmony export */ toggleIncludeCellInAppMetadata: () => (/* binding */ toggleIncludeCellInAppMetadata),
10047
- /* harmony export */ writeCodeToCellByID: () => (/* binding */ writeCodeToCellByID)
10705
+ /* harmony export */ setActiveCellByIDInNotebookPanel: () => (/* binding */ setActiveCellByIDInNotebookPanel),
10706
+ /* harmony export */ writeCodeToCellByID: () => (/* binding */ writeCodeToCellByID),
10707
+ /* harmony export */ writeCodeToCellByIDInNotebookPanel: () => (/* binding */ writeCodeToCellByIDInNotebookPanel)
10048
10708
  /* harmony export */ });
10049
10709
  /* harmony import */ var _jupyterlab_notebook__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @jupyterlab/notebook */ "webpack/sharing/consume/default/@jupyterlab/notebook");
10050
10710
  /* harmony import */ var _jupyterlab_notebook__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_jupyterlab_notebook__WEBPACK_IMPORTED_MODULE_0__);
10051
- /* harmony import */ var _jupyterlab_cells__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @jupyterlab/cells */ "webpack/sharing/consume/default/@jupyterlab/cells");
10052
- /* harmony import */ var _jupyterlab_cells__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_jupyterlab_cells__WEBPACK_IMPORTED_MODULE_1__);
10053
- /* harmony import */ var _strings__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./strings */ "./lib/utils/strings.js");
10711
+ /* harmony import */ var _strings__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./strings */ "./lib/utils/strings.js");
10054
10712
  /*
10055
10713
  * Copyright (c) Saga Inc.
10056
10714
  * Distributed under the terms of the GNU Affero General Public License v3.0 License.
10057
10715
  */
10058
10716
 
10059
10717
 
10060
-
10061
- const INCLUDE_CELL_IN_APP = 'include-cell-in-app';
10062
10718
  const getActiveCell = (notebookTracker) => {
10063
- var _a;
10064
- const notebook = (_a = notebookTracker.currentWidget) === null || _a === void 0 ? void 0 : _a.content;
10065
- const activeCell = notebook === null || notebook === void 0 ? void 0 : notebook.activeCell;
10719
+ const notebookPanel = notebookTracker.currentWidget;
10720
+ return getActiveCellInNotebookPanel(notebookPanel);
10721
+ };
10722
+ const getActiveCellInNotebookPanel = (notebookPanel) => {
10723
+ const activeCell = notebookPanel === null || notebookPanel === void 0 ? void 0 : notebookPanel.content.activeCell;
10066
10724
  return activeCell || undefined;
10067
10725
  };
10068
10726
  const getCellByID = (notebookTracker, cellID) => {
10069
- var _a;
10070
- if (cellID === undefined) {
10071
- return undefined;
10072
- }
10073
- const notebook = (_a = notebookTracker.currentWidget) === null || _a === void 0 ? void 0 : _a.content;
10074
- return notebook === null || notebook === void 0 ? void 0 : notebook.widgets.find(cell => cell.model.id === cellID);
10727
+ const notebook = notebookTracker.currentWidget;
10728
+ return getCellByIDInNotebookPanel(notebook, cellID);
10075
10729
  };
10076
- const toggleActiveCellIncludeInAppMetadata = (notebookTracker) => {
10077
- const activeCellID = getActiveCellID(notebookTracker);
10078
- toggleIncludeCellInAppMetadata(notebookTracker, activeCellID);
10079
- };
10080
- const toggleIncludeCellInAppMetadata = (notebookTracker, cellID) => {
10730
+ const getCellByIDInNotebookPanel = (notebookPanel, cellID) => {
10081
10731
  if (cellID === undefined) {
10082
- return;
10083
- }
10084
- const cell = getCellByID(notebookTracker, cellID);
10085
- if (!cell) {
10086
10732
  return undefined;
10087
10733
  }
10088
- if (Object.prototype.hasOwnProperty.call(cell.model.metadata, INCLUDE_CELL_IN_APP)) {
10089
- const originalVisibility = cell.model.getMetadata(INCLUDE_CELL_IN_APP);
10090
- cell.model.setMetadata(INCLUDE_CELL_IN_APP, !originalVisibility);
10091
- }
10092
- else {
10093
- // If the metadata doesn't exist yet, that means the user has not yet toggled the visibility.
10094
- // The default value is to show the output, so the first toggle should set the visibiltiy to false.
10095
- cell.model.setMetadata(INCLUDE_CELL_IN_APP, false);
10096
- }
10097
- };
10098
- const getActiveCellIncludeInApp = (notebookTracker) => {
10099
- const activeCellID = getActiveCellID(notebookTracker);
10100
- return getIncludeCellInApp(notebookTracker, activeCellID);
10101
- };
10102
- const getIncludeCellInApp = (notebookTracker, cellID) => {
10103
- /*
10104
- Checks the cell metadata tag to see if the user has marked that this cell should not be included in the app.
10105
- */
10106
- const cell = getCellByID(notebookTracker, cellID);
10107
- if (!cell) {
10108
- return false;
10109
- }
10110
- if (!Object.prototype.hasOwnProperty.call(cell.model.metadata, INCLUDE_CELL_IN_APP)) {
10111
- cell.model.setMetadata(INCLUDE_CELL_IN_APP, true);
10112
- }
10113
- return cell.model.getMetadata(INCLUDE_CELL_IN_APP);
10734
+ return notebookPanel === null || notebookPanel === void 0 ? void 0 : notebookPanel.content.widgets.find(cell => cell.model.id === cellID);
10114
10735
  };
10115
10736
  const getActiveCellID = (notebookTracker) => {
10737
+ const notebookPanel = notebookTracker.currentWidget;
10738
+ return getActiveCellIDInNotebookPanel(notebookPanel);
10739
+ };
10740
+ const getActiveCellIDInNotebookPanel = (notebookPanel) => {
10116
10741
  var _a;
10117
- return (_a = getActiveCell(notebookTracker)) === null || _a === void 0 ? void 0 : _a.model.id;
10742
+ return (_a = getActiveCellInNotebookPanel(notebookPanel)) === null || _a === void 0 ? void 0 : _a.model.id;
10118
10743
  };
10119
10744
  const getActiveCellCode = (notebookTracker) => {
10120
10745
  const activeCell = getActiveCell(notebookTracker);
10121
10746
  return activeCell === null || activeCell === void 0 ? void 0 : activeCell.model.sharedModel.source;
10122
10747
  };
10123
10748
  const getCellCodeByID = (notebookTracker, codeCellID) => {
10124
- const cell = getCellByID(notebookTracker, codeCellID);
10125
- return cell === null || cell === void 0 ? void 0 : cell.model.sharedModel.source;
10126
- };
10127
- const getActiveCellOutput = async (notebookTracker) => {
10128
- const activeCellID = getActiveCellID(notebookTracker);
10129
- return getCellOutputByID(notebookTracker, activeCellID);
10749
+ const notebookPanel = notebookTracker.currentWidget;
10750
+ return getCellCodeByIDInNotebookPanel(notebookPanel, codeCellID);
10130
10751
  };
10131
- const getCellOutputByID = async (notebookTracker, codeCellID) => {
10132
- // TODO: There is a bug where if the cell is not actually rendered on the screen,
10133
- // then the output is not captured. This is pretty unlikely to happen currently because
10134
- // the agent scrolls to the cell.
10135
- var _a, _b;
10136
- if (codeCellID === undefined) {
10137
- return undefined;
10138
- }
10139
- const notebook = (_a = notebookTracker.currentWidget) === null || _a === void 0 ? void 0 : _a.content;
10140
- const cell = notebook === null || notebook === void 0 ? void 0 : notebook.widgets.find(cell => cell.model.id === codeCellID);
10141
- if (!(cell instanceof _jupyterlab_cells__WEBPACK_IMPORTED_MODULE_1__.CodeCell)) {
10142
- return undefined;
10143
- }
10144
- const outputNode = (_b = cell.outputArea) === null || _b === void 0 ? void 0 : _b.node;
10145
- if (!outputNode)
10146
- return undefined;
10147
- // Find the top-level Jupyter image output div
10148
- // so we can check if there is a base64 encoded image
10149
- // already constructed for us.
10150
- const renderedImageDiv = outputNode.querySelector('.jp-RenderedImage.jp-OutputArea-output');
10151
- // If the image is the top-level output, then just use that instead
10152
- // of capturing the entire output node. This is much faster and handles
10153
- // matplotlib graphs.
10154
- if (renderedImageDiv) {
10155
- const img = renderedImageDiv.querySelector('img');
10156
- if (img && img.src.startsWith('data:image')) {
10157
- console.log('image found in top-level output');
10158
- // Remove the data URL prefix
10159
- // The img is initially in the format data:image/png;base64, <base64_data>
10160
- // We want to return the base64 data.
10161
- const base64 = img.src.split(',')[1];
10162
- return base64;
10163
- }
10164
- }
10165
- // Fallback: (optional) handle other output types, or use captureNode if needed
10166
- // Previously, we used html2canvas to capture the entire output node. This would
10167
- // give us the output even if it was html, svg, text, etc. However, starting around
10168
- // Chrome release 138, html2canvas became untenably slow. https://issues.chromium.org/issues/429073017
10169
- if (outputNode) {
10170
- // If the AI requested, a cell output that we cannot provide, we just tell it
10171
- // "Cell Output is present in notebook, but not available to share with the AI right now"
10172
- return "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rNkrAoqAIqAIKAKKgCKgCCgCioAioAgoAoqAIqAIKAKKgCKgjliVAUVAEVAEFAFFQBFQBBQBRUARUAQUAUVAEVAEFAFFQBFQBJqMwHDjiP3888+jUPXq1cuMPPLI0TB5+NNPP5mff/5Zfrprz549zfjjj+9+640ioAgoAoqAItAKBP7++28zbNiwpKgxxhijFUWWWsZvv/1murq6TI8ePcxoo41Wat7NzKy7495MbDTv4ROBIvZzEUTKaGvt4r1IvUf0tL/++msCAf0C/YPS8I+A2AOMx0cdddRuVeHuzHu3Ano4YlZ13HD0MptclaY5YocOHWpef/118+qrrxruJ5tsMjP11FObxRZbzIwyyiilVuubb74xvXv3juZ5xRVXmEUWWSQaJg+POOIIc9FFF8lPd11ooYXM1Vdf7X43++aLL74wL7/8snnllVfMOOOMY+aee24zxxxzmO44CG82Vp2Y//TTT5+wtdlmm5n+/ft3IovKkyLgENhuu+3Mvffem+jlBx54wD3Xm85A4PLLLzf9+vVLmBk8eLCZccYZO4OxBrmg//z222+Tfuymm25qMFX7o3V33NuPoHLQbgReeukls/baaydsDBo0yKyxxhqpLBW1n1MzbiCgaFtrJ+8NVE+jRBB47733zPLLL5+EHH744aZPnz6RWPqoVQi0atwi9sBKK61kzjzzzFZVr5RyujPvPgA4lPHLCPHuxxtvPPlZdf3hhx/Mu+++W/U89mDKKac0E088cSyoY55l6ReLMK06rgh6I17a0h2xzALsv//+5vbbb4+iOeaYY5oTTjjBrLjiitHwPA+/++47s+CCC0aTNuKIHTBggLnggguq0rfKEcuqgEMOOcRceeWVVTzw4PzzzzfLLLNMNKyshy+++KIZMmRIkt1WW21lJpxwwrKybno+ncK7GDQbbrihGThwYNPrrQV0TwQ6RV633nprgwN20kknNY899lj3BLOFXN92223mjTfeMKOPPrrp27dv00u+7LLLkn6Bgu6++24z00wzNb3MMguQwQsTit3JEdspuGPXiF2ywgormHnmmafM19PRebW6rXU0GDmYe/755816662XpDzxxBOdUzaWVVH7OZZno8+KtrV28t5oHRuJNyLJu++kOOyww8wWW2zRCEQap0kI5Bm35JHXueaay/zyyy+m3Y7Y7sx7URG48847K2zX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";
10173
- }
10174
- return undefined;
10752
+ const getCellCodeByIDInNotebookPanel = (notebookPanel, codeCellID) => {
10753
+ const cell = getCellByIDInNotebookPanel(notebookPanel, codeCellID);
10754
+ return cell === null || cell === void 0 ? void 0 : cell.model.sharedModel.source;
10175
10755
  };
10176
10756
  const getCellIndexByID = (notebookTracker, cellID) => {
10177
- var _a, _b;
10178
- const cellList = (_b = (_a = notebookTracker.currentWidget) === null || _a === void 0 ? void 0 : _a.model) === null || _b === void 0 ? void 0 : _b.cells;
10757
+ const notebookPanel = notebookTracker.currentWidget;
10758
+ return getCellIndexByIDInNotebookPanel(notebookPanel, cellID);
10759
+ };
10760
+ const getCellIndexByIDInNotebookPanel = (notebookPanel, cellID) => {
10761
+ var _a;
10762
+ const cellList = (_a = notebookPanel === null || notebookPanel === void 0 ? void 0 : notebookPanel.model) === null || _a === void 0 ? void 0 : _a.cells;
10179
10763
  if (cellList === undefined) {
10180
10764
  return undefined;
10181
10765
  }
@@ -10190,28 +10774,38 @@ const getCellIndexByID = (notebookTracker, cellID) => {
10190
10774
  return undefined;
10191
10775
  };
10192
10776
  const setActiveCellByID = (notebookTracker, cellID) => {
10193
- const cellIndex = getCellIndexByID(notebookTracker, cellID);
10194
10777
  const notebookPanel = notebookTracker.currentWidget;
10195
- if (notebookPanel !== undefined && notebookPanel !== null && cellIndex !== undefined) {
10778
+ setActiveCellByIDInNotebookPanel(notebookPanel, cellID);
10779
+ };
10780
+ const setActiveCellByIDInNotebookPanel = (notebookPanel, cellID) => {
10781
+ const cellIndex = getCellIndexByIDInNotebookPanel(notebookPanel, cellID);
10782
+ if (cellIndex !== undefined && notebookPanel !== null) {
10196
10783
  notebookPanel.content.activeCellIndex = cellIndex;
10197
10784
  }
10198
10785
  };
10199
10786
  const writeCodeToCellByID = (notebookTracker, code, codeCellID) => {
10200
- var _a;
10201
- if (code === undefined) {
10787
+ const notebookPanel = notebookTracker.currentWidget;
10788
+ writeCodeToCellByIDInNotebookPanel(notebookPanel, code, codeCellID);
10789
+ };
10790
+ const writeCodeToCellByIDInNotebookPanel = (notebookPanel, code, codeCellID) => {
10791
+ if (code === undefined || codeCellID === undefined) {
10202
10792
  return;
10203
10793
  }
10204
- const codeMirrorValidCode = (0,_strings__WEBPACK_IMPORTED_MODULE_2__.removeMarkdownCodeFormatting)(code);
10205
- const notebook = (_a = notebookTracker.currentWidget) === null || _a === void 0 ? void 0 : _a.content;
10794
+ const codeMirrorValidCode = (0,_strings__WEBPACK_IMPORTED_MODULE_1__.removeMarkdownCodeFormatting)(code);
10795
+ const notebook = notebookPanel === null || notebookPanel === void 0 ? void 0 : notebookPanel.content;
10206
10796
  const cell = notebook === null || notebook === void 0 ? void 0 : notebook.widgets.find(cell => cell.model.id === codeCellID);
10207
10797
  if (cell) {
10208
10798
  cell.model.sharedModel.source = codeMirrorValidCode;
10209
10799
  }
10210
10800
  };
10211
10801
  const getAIOptimizedCells = (notebookTracker) => {
10212
- var _a, _b;
10213
- const cellList = (_b = (_a = notebookTracker.currentWidget) === null || _a === void 0 ? void 0 : _a.model) === null || _b === void 0 ? void 0 : _b.cells;
10214
- if (cellList == undefined) {
10802
+ const notebookPanel = notebookTracker.currentWidget;
10803
+ return getAIOptimizedCellsInNotebookPanel(notebookPanel);
10804
+ };
10805
+ const getAIOptimizedCellsInNotebookPanel = (notebookPanel) => {
10806
+ var _a;
10807
+ const cellList = (_a = notebookPanel === null || notebookPanel === void 0 ? void 0 : notebookPanel.model) === null || _a === void 0 ? void 0 : _a.cells;
10808
+ if (cellList == undefined || cellList == null) {
10215
10809
  return [];
10216
10810
  }
10217
10811
  // In order to get the cell index, we need to iterate over the cells and call the `get` method
@@ -10228,12 +10822,11 @@ const getAIOptimizedCells = (notebookTracker) => {
10228
10822
  }
10229
10823
  return cells;
10230
10824
  };
10231
- function createCodeCellAtIndexAndActivate(notebookTracker, index) {
10825
+ function createCodeCellAtIndexAndActivate(notebookPanel, index) {
10232
10826
  /*
10233
10827
  Create a new code cell at index and make it the active cell.
10234
10828
  */
10235
- var _a;
10236
- const notebook = (_a = notebookTracker.currentWidget) === null || _a === void 0 ? void 0 : _a.content;
10829
+ const notebook = notebookPanel.content;
10237
10830
  if (notebook === undefined) {
10238
10831
  return;
10239
10832
  }
@@ -10280,7 +10873,7 @@ const highlightCodeCell = (notebookTracker, codeCellID) => {
10280
10873
  }, 500);
10281
10874
  }
10282
10875
  };
10283
- const highlightLinesOfCodeInCodeCell = (notebookTracker, codeCellID, startLine, endLine) => {
10876
+ const highlightLinesOfCodeInCodeCell = (notebookPanel, codeCellID, startLine, endLine) => {
10284
10877
  /*
10285
10878
  Briefly highlights a range of lines in a code cell, to draw the user's attention to it.
10286
10879
 
@@ -10293,7 +10886,7 @@ const highlightLinesOfCodeInCodeCell = (notebookTracker, codeCellID, startLine,
10293
10886
  endLine: The 0-indexed end line number to highlight (inclusive).
10294
10887
  */
10295
10888
  // Get the cell with the given ID
10296
- const cell = getCellByID(notebookTracker, codeCellID);
10889
+ const cell = getCellByIDInNotebookPanel(notebookPanel, codeCellID);
10297
10890
  if (!cell) {
10298
10891
  return;
10299
10892
  }
@@ -10337,42 +10930,44 @@ const highlightLinesOfCodeInCodeCell = (notebookTracker, codeCellID, startLine,
10337
10930
  });
10338
10931
  }, 2000);
10339
10932
  };
10340
- const scrollToAndHighlightCell = (notebookTracker, cellID, startLine, endLine, position = 'center') => {
10933
+ const scrollToAndHighlightCell = (notebookPanel, cellID, startLine, endLine, position = 'center') => {
10934
+ if (notebookPanel === null) {
10935
+ return;
10936
+ }
10341
10937
  // Scroll to the cell
10342
- scrollToCell(notebookTracker, cellID, startLine, position);
10938
+ scrollToCell(notebookPanel, cellID, startLine, position);
10343
10939
  // Wait for the scroll animation to complete before highlighting the lines
10344
10940
  // The default smooth scroll takes about 300-500ms to complete
10345
10941
  setTimeout(() => {
10346
10942
  if (startLine !== undefined) {
10347
10943
  // If no end line was provided, then we just highlight the single line
10348
10944
  endLine = endLine || startLine;
10349
- highlightLinesOfCodeInCodeCell(notebookTracker, cellID, startLine, endLine);
10945
+ highlightLinesOfCodeInCodeCell(notebookPanel, cellID, startLine, endLine);
10350
10946
  }
10351
10947
  else {
10352
10948
  // If no start line was provided, then we just highlight the entire cell
10353
- highlightLinesOfCodeInCodeCell(notebookTracker, cellID, undefined, undefined);
10949
+ highlightLinesOfCodeInCodeCell(notebookPanel, cellID, undefined, undefined);
10354
10950
  }
10355
10951
  }, 500);
10356
10952
  };
10357
- const scrollToCell = (notebookTracker, cellID, startLine, position = 'center') => {
10358
- var _a;
10953
+ const scrollToCell = (notebookPanel, cellID, startLine, position = 'center') => {
10359
10954
  // Get the cell
10360
- const cell = getCellByID(notebookTracker, cellID);
10361
- if (!cell) {
10955
+ const cell = getCellByIDInNotebookPanel(notebookPanel, cellID);
10956
+ if (!cell || notebookPanel === null) {
10362
10957
  return;
10363
10958
  }
10364
10959
  // If line numbers are provided, figure out what position to scroll to
10365
10960
  // based on the start line's position in the cell
10366
- const code = getCellCodeByID(notebookTracker, cellID);
10961
+ const code = getCellCodeByIDInNotebookPanel(notebookPanel, cellID);
10367
10962
  startLine = startLine || 0;
10368
10963
  const relativeLinePosition = startLine / ((code === null || code === void 0 ? void 0 : code.split('\n').length) || 1);
10369
10964
  // These positions must be of type BaseScrollToAlignment defined in @jupyterlab/ui-components
10370
10965
  position = relativeLinePosition < 0.5 ? 'start' : 'end';
10371
10966
  // If the cell is not the active cell, the scrolling does not work.
10372
10967
  // It scrolls to the cell and then flashes back to the active cell.
10373
- setActiveCellByID(notebookTracker, cellID);
10968
+ setActiveCellByIDInNotebookPanel(notebookPanel, cellID);
10374
10969
  // Use the new JupyterLab scrollToCell method instead of DOM node scrollIntoView
10375
- void ((_a = notebookTracker.currentWidget) === null || _a === void 0 ? void 0 : _a.content.scrollToCell(cell, position));
10970
+ void notebookPanel.content.scrollToCell(cell, position);
10376
10971
  };
10377
10972
 
10378
10973
 
@@ -10683,7 +11278,8 @@ const STRIPE_PAYMENT_LINK = "https://jl76z192i0.execute-api.us-east-1.amazonaws.
10683
11278
  __webpack_require__.r(__webpack_exports__);
10684
11279
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
10685
11280
  /* harmony export */ getOperatingSystem: () => (/* binding */ getOperatingSystem),
10686
- /* harmony export */ isChromeBasedBrowser: () => (/* binding */ isChromeBasedBrowser)
11281
+ /* harmony export */ isChromeBasedBrowser: () => (/* binding */ isChromeBasedBrowser),
11282
+ /* harmony export */ isElectronBasedFrontend: () => (/* binding */ isElectronBasedFrontend)
10687
11283
  /* harmony export */ });
10688
11284
  /*
10689
11285
  * Copyright (c) Saga Inc.
@@ -10700,6 +11296,14 @@ const getOperatingSystem = () => {
10700
11296
  const isChromeBasedBrowser = () => {
10701
11297
  return /chrome/i.test(navigator.userAgent) && !/edge|edg/i.test(navigator.userAgent);
10702
11298
  };
11299
+ const isElectronBasedFrontend = () => {
11300
+ /*
11301
+ Checks if the user is using an Electron-based browser.
11302
+ This tells us that they are using Mito Desktop or JupyterLab Desktop.
11303
+ */
11304
+ const userAgent = navigator.userAgent.toLowerCase();
11305
+ return userAgent.includes('electron');
11306
+ };
10703
11307
 
10704
11308
 
10705
11309
  /***/ }),
@@ -11272,15 +11876,15 @@ class BaseWebsocketClient {
11272
11876
 
11273
11877
  /***/ }),
11274
11878
 
11275
- /***/ "./lib/websockets/appBuilder/appBuilderWebsocketClient.js":
11276
- /*!****************************************************************!*\
11277
- !*** ./lib/websockets/appBuilder/appBuilderWebsocketClient.js ***!
11278
- \****************************************************************/
11879
+ /***/ "./lib/websockets/appDeploy/appDeployWebsocketClient.js":
11880
+ /*!**************************************************************!*\
11881
+ !*** ./lib/websockets/appDeploy/appDeployWebsocketClient.js ***!
11882
+ \**************************************************************/
11279
11883
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
11280
11884
 
11281
11885
  __webpack_require__.r(__webpack_exports__);
11282
11886
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
11283
- /* harmony export */ AppBuilderWebsocketClient: () => (/* binding */ AppBuilderWebsocketClient)
11887
+ /* harmony export */ AppDeployWebsocketClient: () => (/* binding */ AppDeployWebsocketClient)
11284
11888
  /* harmony export */ });
11285
11889
  /* harmony import */ var _BaseWebsocketClient__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../BaseWebsocketClient */ "./lib/websockets/BaseWebsocketClient.js");
11286
11890
  /*
@@ -11293,7 +11897,7 @@ __webpack_require__.r(__webpack_exports__);
11293
11897
  *
11294
11898
  * It communicates with the backend over a WebSocket for app building functionality.
11295
11899
  */
11296
- class AppBuilderWebsocketClient extends _BaseWebsocketClient__WEBPACK_IMPORTED_MODULE_0__.BaseWebsocketClient {
11900
+ class AppDeployWebsocketClient extends _BaseWebsocketClient__WEBPACK_IMPORTED_MODULE_0__.BaseWebsocketClient {
11297
11901
  /**
11298
11902
  * Create a new app builder client.
11299
11903
  */
@@ -11302,7 +11906,7 @@ class AppBuilderWebsocketClient extends _BaseWebsocketClient__WEBPACK_IMPORTED_M
11302
11906
  /**
11303
11907
  * The service URL for the websocket endpoint.
11304
11908
  */
11305
- this.SERVICE_URL = 'mito-ai/app-builder';
11909
+ this.SERVICE_URL = 'mito-ai/app-deploy';
11306
11910
  }
11307
11911
  /**
11308
11912
  * App builder messages stream.
@@ -11467,11 +12071,13 @@ __webpack_require__.r(__webpack_exports__);
11467
12071
  /* harmony export */ CompletionWebsocketClient: () => (/* binding */ CompletionWebsocketClient)
11468
12072
  /* harmony export */ });
11469
12073
  /* harmony import */ var _BaseWebsocketClient__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../BaseWebsocketClient */ "./lib/websockets/BaseWebsocketClient.js");
12074
+ /* harmony import */ var _utils_user__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../utils/user */ "./lib/utils/user.js");
11470
12075
  /*
11471
12076
  * Copyright (c) Saga Inc.
11472
12077
  * Distributed under the terms of the GNU Affero General Public License v3.0 License.
11473
12078
  */
11474
12079
 
12080
+
11475
12081
  /**
11476
12082
  * Mito AI completion client
11477
12083
  *
@@ -11487,6 +12093,7 @@ class CompletionWebsocketClient extends _BaseWebsocketClient__WEBPACK_IMPORTED_M
11487
12093
  * The service URL for the websocket endpoint.
11488
12094
  */
11489
12095
  this.SERVICE_URL = 'mito-ai/completions';
12096
+ this.isElectron = (0,_utils_user__WEBPACK_IMPORTED_MODULE_1__.isElectronBasedFrontend)();
11490
12097
  }
11491
12098
  /**
11492
12099
  * Completion chunk stream.
@@ -11558,6 +12165,17 @@ class CompletionWebsocketClient extends _BaseWebsocketClient__WEBPACK_IMPORTED_M
11558
12165
  // default: /* no-op */
11559
12166
  }
11560
12167
  }
12168
+ // Override sendMessage to automatically add environment info
12169
+ sendMessage(message) {
12170
+ // Add environment info to all messages
12171
+ const messageWithEnvironment = {
12172
+ ...message,
12173
+ environment: {
12174
+ isElectron: this.isElectron,
12175
+ }
12176
+ };
12177
+ return super.sendMessage(messageWithEnvironment);
12178
+ }
11561
12179
  }
11562
12180
 
11563
12181
 
@@ -12758,6 +13376,8 @@ ___CSS_LOADER_EXPORT___.push([module.id, `/*
12758
13376
  margin: 0;
12759
13377
  width: 100%;
12760
13378
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
13379
+ overflow-y: auto;
13380
+ max-height: 350px;
12761
13381
  }
12762
13382
 
12763
13383
  .chat-dropdown-item {
@@ -12842,7 +13462,7 @@ ___CSS_LOADER_EXPORT___.push([module.id, `/*
12842
13462
  .chat-dropdown-search-input::placeholder {
12843
13463
  color: var(--jp-content-font-color3);
12844
13464
  }
12845
- `, "",{"version":3,"sources":["webpack://./style/ChatDropdown.css"],"names":[],"mappings":"AAAA;;;EAGE;;AAEF;EACE,4CAA4C;EAC5C,kBAAkB;EAClB,aAAa;EACb,YAAY;EACZ,kBAAkB;;EAElB,uBAAuB;EACvB,aAAa;EACb,sBAAsB;EACtB,WAAW;EACX,yCAAyC;EACzC,kBAAkB;AACpB;;AAEA;EACE,kBAAkB;EAClB,WAAW;EACX,kBAAkB;EAClB,yCAAyC;EACzC,qBAAqB;EACrB,UAAU;EACV,SAAS;EACT,WAAW;EACX,wCAAwC;AAC1C;;AAEA;EACE,YAAY;EACZ,eAAe;EACf,aAAa;EACb,mBAAmB;EACnB,QAAQ;EACR,oCAAoC;EACpC,gBAAgB;EAChB,uBAAuB;EACvB,mBAAmB;AACrB;;AAEA;;EAEE,yCAAyC;AAC3C;;AAEA;EACE,6BAA6B;EAC7B,uCAAuC;EACvC,eAAe;EACf,WAAW;EACX,mBAAmB;EACnB,gBAAgB;EAChB,uBAAuB;AACzB;;AAEA;EACE,eAAe;EACf,aAAa;EACb,mBAAmB;EACnB,mBAAmB;EACnB,gBAAgB;EAChB,uBAAuB;AACzB;;AAEA;EACE,8BAA8B;EAC9B,eAAe;EACf,gBAAgB;EAChB,mBAAmB;EACnB,gBAAgB;EAChB,uBAAuB;AACzB;;AAEA;EACE,YAAY;EACZ,mBAAmB;AACrB;;AAEA;EACE,yBAAyB;AAC3B;;AAEA;EACE,YAAY;EACZ,yCAAyC;EACzC,2BAA2B;EAC3B,4BAA4B;AAC9B;;AAEA;EACE,WAAW;EACX,gBAAgB;EAChB,kBAAkB;EAClB,eAAe;EACf,qCAAqC;EACrC,yCAAyC;EACzC,oCAAoC;EACpC,aAAa;EACb,YAAY;EACZ,sBAAsB;AACxB;;AAEA;EACE,aAAa;EACb,YAAY;AACd;;AAEA;EACE,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.chat-dropdown {\n /* Position the dropdown in the right place*/\n position: absolute;\n z-index: 9999;\n bottom: 100%;\n margin-bottom: 5px;\n\n /* Style the dropdown */\n display: flex;\n flex-direction: column;\n width: 100%;\n border: 1px solid var(--jp-border-color1);\n border-radius: 5px;\n}\n\n.chat-dropdown-list {\n position: relative;\n border: 0px;\n border-radius: 5px;\n background-color: var(--jp-layout-color1);\n list-style-type: none;\n padding: 0;\n margin: 0;\n width: 100%;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\n}\n\n.chat-dropdown-item {\n padding: 8px;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 8px;\n color: var(--jp-content-font-color1);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.chat-dropdown-item:hover,\n.chat-dropdown-item.selected {\n background-color: var(--jp-layout-color3);\n}\n\n.chat-dropdown-item-type {\n color: var(--jp-brand-color1);\n font-family: var(--jp-code-font-family);\n min-width: 35px;\n width: 35px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.chat-dropdown-item-name {\n font-size: 15px;\n display: flex;\n align-items: center;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.chat-dropdown-item-parent-df {\n color: var(--muted-text-color);\n font-size: 12px;\n margin-left: 4px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.dropdown-item-disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.dropdown-item-disabled:hover {\n background-color: inherit;\n}\n\n.chat-dropdown-search {\n padding: 8px;\n background-color: var(--jp-layout-color1);\n border-top-left-radius: 5px;\n border-top-right-radius: 5px;\n}\n\n.chat-dropdown-search-input {\n width: 100%;\n padding: 6px 8px;\n border-radius: 3px;\n font-size: 12px;\n font-family: var(--jp-ui-font-family);\n background-color: var(--jp-layout-color1);\n color: var(--jp-content-font-color1);\n outline: none;\n border: none;\n box-sizing: border-box;\n}\n\n.chat-dropdown-search-input:focus {\n outline: none;\n border: none;\n}\n\n.chat-dropdown-search-input::placeholder {\n color: var(--jp-content-font-color3);\n}\n"],"sourceRoot":""}]);
13465
+ `, "",{"version":3,"sources":["webpack://./style/ChatDropdown.css"],"names":[],"mappings":"AAAA;;;EAGE;;AAEF;EACE,4CAA4C;EAC5C,kBAAkB;EAClB,aAAa;EACb,YAAY;EACZ,kBAAkB;;EAElB,uBAAuB;EACvB,aAAa;EACb,sBAAsB;EACtB,WAAW;EACX,yCAAyC;EACzC,kBAAkB;AACpB;;AAEA;EACE,kBAAkB;EAClB,WAAW;EACX,kBAAkB;EAClB,yCAAyC;EACzC,qBAAqB;EACrB,UAAU;EACV,SAAS;EACT,WAAW;EACX,wCAAwC;EACxC,gBAAgB;EAChB,iBAAiB;AACnB;;AAEA;EACE,YAAY;EACZ,eAAe;EACf,aAAa;EACb,mBAAmB;EACnB,QAAQ;EACR,oCAAoC;EACpC,gBAAgB;EAChB,uBAAuB;EACvB,mBAAmB;AACrB;;AAEA;;EAEE,yCAAyC;AAC3C;;AAEA;EACE,6BAA6B;EAC7B,uCAAuC;EACvC,eAAe;EACf,WAAW;EACX,mBAAmB;EACnB,gBAAgB;EAChB,uBAAuB;AACzB;;AAEA;EACE,eAAe;EACf,aAAa;EACb,mBAAmB;EACnB,mBAAmB;EACnB,gBAAgB;EAChB,uBAAuB;AACzB;;AAEA;EACE,8BAA8B;EAC9B,eAAe;EACf,gBAAgB;EAChB,mBAAmB;EACnB,gBAAgB;EAChB,uBAAuB;AACzB;;AAEA;EACE,YAAY;EACZ,mBAAmB;AACrB;;AAEA;EACE,yBAAyB;AAC3B;;AAEA;EACE,YAAY;EACZ,yCAAyC;EACzC,2BAA2B;EAC3B,4BAA4B;AAC9B;;AAEA;EACE,WAAW;EACX,gBAAgB;EAChB,kBAAkB;EAClB,eAAe;EACf,qCAAqC;EACrC,yCAAyC;EACzC,oCAAoC;EACpC,aAAa;EACb,YAAY;EACZ,sBAAsB;AACxB;;AAEA;EACE,aAAa;EACb,YAAY;AACd;;AAEA;EACE,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.chat-dropdown {\n /* Position the dropdown in the right place*/\n position: absolute;\n z-index: 9999;\n bottom: 100%;\n margin-bottom: 5px;\n\n /* Style the dropdown */\n display: flex;\n flex-direction: column;\n width: 100%;\n border: 1px solid var(--jp-border-color1);\n border-radius: 5px;\n}\n\n.chat-dropdown-list {\n position: relative;\n border: 0px;\n border-radius: 5px;\n background-color: var(--jp-layout-color1);\n list-style-type: none;\n padding: 0;\n margin: 0;\n width: 100%;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\n overflow-y: auto;\n max-height: 350px;\n}\n\n.chat-dropdown-item {\n padding: 8px;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 8px;\n color: var(--jp-content-font-color1);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.chat-dropdown-item:hover,\n.chat-dropdown-item.selected {\n background-color: var(--jp-layout-color3);\n}\n\n.chat-dropdown-item-type {\n color: var(--jp-brand-color1);\n font-family: var(--jp-code-font-family);\n min-width: 35px;\n width: 35px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.chat-dropdown-item-name {\n font-size: 15px;\n display: flex;\n align-items: center;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.chat-dropdown-item-parent-df {\n color: var(--muted-text-color);\n font-size: 12px;\n margin-left: 4px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.dropdown-item-disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.dropdown-item-disabled:hover {\n background-color: inherit;\n}\n\n.chat-dropdown-search {\n padding: 8px;\n background-color: var(--jp-layout-color1);\n border-top-left-radius: 5px;\n border-top-right-radius: 5px;\n}\n\n.chat-dropdown-search-input {\n width: 100%;\n padding: 6px 8px;\n border-radius: 3px;\n font-size: 12px;\n font-family: var(--jp-ui-font-family);\n background-color: var(--jp-layout-color1);\n color: var(--jp-content-font-color1);\n outline: none;\n border: none;\n box-sizing: border-box;\n}\n\n.chat-dropdown-search-input:focus {\n outline: none;\n border: none;\n}\n\n.chat-dropdown-search-input::placeholder {\n color: var(--jp-content-font-color3);\n}\n"],"sourceRoot":""}]);
12846
13466
  // Exports
12847
13467
  /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);
12848
13468
 
@@ -12888,6 +13508,10 @@ ___CSS_LOADER_EXPORT___.push([module.id, `/*
12888
13508
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
12889
13509
  }
12890
13510
 
13511
+ .chat-input-container.editing {
13512
+ margin-top: 0;
13513
+ }
13514
+
12891
13515
  .chat-input-text-area-container {
12892
13516
  position: relative;
12893
13517
  height: min-content;
@@ -12899,7 +13523,7 @@ ___CSS_LOADER_EXPORT___.push([module.id, `/*
12899
13523
  resize: none;
12900
13524
  width: 100%;
12901
13525
  padding: 10px;
12902
- overflow-y: hidden;
13526
+ overflow-y: auto;
12903
13527
  box-sizing: border-box;
12904
13528
  flex-shrink: 0 !important;
12905
13529
  background-color: var(--chat-user-message-background-color);
@@ -12968,7 +13592,7 @@ ___CSS_LOADER_EXPORT___.push([module.id, `/*
12968
13592
 
12969
13593
  .context-button:disabled:hover {
12970
13594
  background-color: var(--jp-layout-color2);
12971
- }`, "",{"version":3,"sources":["webpack://./style/ChatInput.css"],"names":[],"mappings":"AAAA;;;EAGE;;AAEF;EACE,gBAAgB;EAChB,SAAS;EACT,cAAc;EACd,gBAAgB;EAChB,2DAA2D;EAC3D;;;iCAG+B;EAC/B,WAAW;EACX,mBAAmB;EACnB,iDAAiD;AACnD;;AAEA;EACE,kBAAkB;EAClB,mBAAmB;AACrB;;AAEA;EACE,aAAa;EACb,YAAY;EACZ,YAAY;EACZ,WAAW;EACX,aAAa;EACb,kBAAkB;EAClB,sBAAsB;EACtB,yBAAyB;EACzB,2DAA2D;EAC3D,eAAe;EACf,gBAAgB;EAChB,qCAAqC;EACrC,gBAAgB;EAChB,iDAAiD;AACnD;;AAEA;EACE,aAAa;AACf;;AAEA;EACE,2BAA2B;EAC3B;;;iCAG+B;AACjC;;AAEA;EACE,+BAA+B;AACjC;;AAEA;EACE,+BAA+B;EAC/B,2BAA2B;AAC7B;;AAEA;EACE,+BAA+B;AACjC;;AAEA;EACE,aAAa;EACb,mBAAmB;EACnB,yCAAyC;EACzC,yCAAyC;EACzC,kBAAkB;EAClB,gBAAgB;EAChB,eAAe;EACf,yCAAyC;EACzC,eAAe;EACf,oCAAoC;EACpC,sCAAsC;AACxC;;AAEA;EACE,yCAAyC;AAC3C;;AAEA,0BAA0B;AAC1B;EACE,YAAY;EACZ,mBAAmB;EACnB,yCAAyC;AAC3C;;AAEA;EACE,YAAY;EACZ,mBAAmB;EACnB,yCAAyC;AAC3C;;AAEA;EACE,yCAAyC;AAC3C","sourcesContent":["/*\n * Copyright (c) Saga Inc.\n * Distributed under the terms of the GNU Affero General Public License v3.0 License.\n */\n\n.chat-input-container {\n position: sticky;\n bottom: 0;\n margin: 10px 0;\n margin-top: auto;\n background-color: var(--chat-user-message-background-color);\n box-shadow: \n 0 4px 12px rgba(0, 0, 0, 0.08),\n 0 2px 4px rgba(0, 0, 0, 0.06),\n 0 0 0 1px rgba(0, 0, 0, 0.02);\n width: 100%;\n border-radius: 12px;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.chat-input-text-area-container {\n position: relative;\n height: min-content;\n}\n\n.chat-input {\n outline: none;\n border: none;\n resize: none;\n width: 100%;\n padding: 10px;\n overflow-y: hidden;\n box-sizing: border-box;\n flex-shrink: 0 !important;\n background-color: var(--chat-user-message-background-color);\n font-size: 12px;\n font-weight: 400;\n font-family: var(--jp-ui-font-family);\n line-height: 1.2;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.active-cell-preview-container {\n padding: 10px;\n}\n\n.chat-input-container:focus-within {\n transform: translateY(-1px);\n box-shadow: \n 0 2px 8px rgba(0, 0, 0, 0.12),\n 0 8px 16px rgba(0, 0, 0, 0.08),\n 0 0 0 1px rgba(0, 0, 0, 0.04);\n}\n\n.chat-input:focus {\n color: var(--jp-ui-font-color1);\n}\n\n.chat-input::placeholder {\n color: var(--jp-ui-font-color2);\n transition: color 0.2s ease;\n}\n\n.chat-input:focus::placeholder {\n color: var(--jp-ui-font-color3);\n}\n\n.context-button {\n display: flex;\n align-items: center;\n background-color: var(--jp-layout-color2);\n border: 1px solid var(--jp-border-color1);\n border-radius: 3px;\n padding: 4px 8px;\n font-size: 12px;\n height: var(--chat-context-button-height);\n cursor: pointer;\n color: var(--jp-content-font-color1);\n transition: background-color 0.2s ease;\n}\n\n.context-button:hover {\n background-color: var(--jp-layout-color3);\n}\n\n/* Disabled state styles */\n.chat-input:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n background-color: var(--jp-layout-color2);\n}\n\n.context-button:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n background-color: var(--jp-layout-color2);\n}\n\n.context-button:disabled:hover {\n background-color: var(--jp-layout-color2);\n}"],"sourceRoot":""}]);
13595
+ }`, "",{"version":3,"sources":["webpack://./style/ChatInput.css"],"names":[],"mappings":"AAAA;;;EAGE;;AAEF;EACE,gBAAgB;EAChB,SAAS;EACT,cAAc;EACd,gBAAgB;EAChB,2DAA2D;EAC3D;;;iCAG+B;EAC/B,WAAW;EACX,mBAAmB;EACnB,iDAAiD;AACnD;;AAEA;EACE,aAAa;AACf;;AAEA;EACE,kBAAkB;EAClB,mBAAmB;AACrB;;AAEA;EACE,aAAa;EACb,YAAY;EACZ,YAAY;EACZ,WAAW;EACX,aAAa;EACb,gBAAgB;EAChB,sBAAsB;EACtB,yBAAyB;EACzB,2DAA2D;EAC3D,eAAe;EACf,gBAAgB;EAChB,qCAAqC;EACrC,gBAAgB;EAChB,iDAAiD;AACnD;;AAEA;EACE,aAAa;AACf;;AAEA;EACE,2BAA2B;EAC3B;;;iCAG+B;AACjC;;AAEA;EACE,+BAA+B;AACjC;;AAEA;EACE,+BAA+B;EAC/B,2BAA2B;AAC7B;;AAEA;EACE,+BAA+B;AACjC;;AAEA;EACE,aAAa;EACb,mBAAmB;EACnB,yCAAyC;EACzC,yCAAyC;EACzC,kBAAkB;EAClB,gBAAgB;EAChB,eAAe;EACf,yCAAyC;EACzC,eAAe;EACf,oCAAoC;EACpC,sCAAsC;AACxC;;AAEA;EACE,yCAAyC;AAC3C;;AAEA,0BAA0B;AAC1B;EACE,YAAY;EACZ,mBAAmB;EACnB,yCAAyC;AAC3C;;AAEA;EACE,YAAY;EACZ,mBAAmB;EACnB,yCAAyC;AAC3C;;AAEA;EACE,yCAAyC;AAC3C","sourcesContent":["/*\n * Copyright (c) Saga Inc.\n * Distributed under the terms of the GNU Affero General Public License v3.0 License.\n */\n\n.chat-input-container {\n position: sticky;\n bottom: 0;\n margin: 10px 0;\n margin-top: auto;\n background-color: var(--chat-user-message-background-color);\n box-shadow: \n 0 4px 12px rgba(0, 0, 0, 0.08),\n 0 2px 4px rgba(0, 0, 0, 0.06),\n 0 0 0 1px rgba(0, 0, 0, 0.02);\n width: 100%;\n border-radius: 12px;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.chat-input-container.editing {\n margin-top: 0;\n}\n\n.chat-input-text-area-container {\n position: relative;\n height: min-content;\n}\n\n.chat-input {\n outline: none;\n border: none;\n resize: none;\n width: 100%;\n padding: 10px;\n overflow-y: auto;\n box-sizing: border-box;\n flex-shrink: 0 !important;\n background-color: var(--chat-user-message-background-color);\n font-size: 12px;\n font-weight: 400;\n font-family: var(--jp-ui-font-family);\n line-height: 1.2;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.active-cell-preview-container {\n padding: 10px;\n}\n\n.chat-input-container:focus-within {\n transform: translateY(-1px);\n box-shadow: \n 0 2px 8px rgba(0, 0, 0, 0.12),\n 0 8px 16px rgba(0, 0, 0, 0.08),\n 0 0 0 1px rgba(0, 0, 0, 0.04);\n}\n\n.chat-input:focus {\n color: var(--jp-ui-font-color1);\n}\n\n.chat-input::placeholder {\n color: var(--jp-ui-font-color2);\n transition: color 0.2s ease;\n}\n\n.chat-input:focus::placeholder {\n color: var(--jp-ui-font-color3);\n}\n\n.context-button {\n display: flex;\n align-items: center;\n background-color: var(--jp-layout-color2);\n border: 1px solid var(--jp-border-color1);\n border-radius: 3px;\n padding: 4px 8px;\n font-size: 12px;\n height: var(--chat-context-button-height);\n cursor: pointer;\n color: var(--jp-content-font-color1);\n transition: background-color 0.2s ease;\n}\n\n.context-button:hover {\n background-color: var(--jp-layout-color3);\n}\n\n/* Disabled state styles */\n.chat-input:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n background-color: var(--jp-layout-color2);\n}\n\n.context-button:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n background-color: var(--jp-layout-color2);\n}\n\n.context-button:disabled:hover {\n background-color: var(--jp-layout-color2);\n}"],"sourceRoot":""}]);
12972
13596
  // Exports
12973
13597
  /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);
12974
13598
 
@@ -14241,6 +14865,142 @@ ___CSS_LOADER_EXPORT___.push([module.id, `/*
14241
14865
  /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);
14242
14866
 
14243
14867
 
14868
+ /***/ }),
14869
+
14870
+ /***/ "./node_modules/css-loader/dist/cjs.js!./style/FilesSelector.css":
14871
+ /*!***********************************************************************!*\
14872
+ !*** ./node_modules/css-loader/dist/cjs.js!./style/FilesSelector.css ***!
14873
+ \***********************************************************************/
14874
+ /***/ ((module, __webpack_exports__, __webpack_require__) => {
14875
+
14876
+ __webpack_require__.r(__webpack_exports__);
14877
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
14878
+ /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
14879
+ /* harmony export */ });
14880
+ /* harmony import */ var _node_modules_css_loader_dist_runtime_sourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../node_modules/css-loader/dist/runtime/sourceMaps.js */ "./node_modules/css-loader/dist/runtime/sourceMaps.js");
14881
+ /* harmony import */ var _node_modules_css_loader_dist_runtime_sourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_sourceMaps_js__WEBPACK_IMPORTED_MODULE_0__);
14882
+ /* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../node_modules/css-loader/dist/runtime/api.js */ "./node_modules/css-loader/dist/runtime/api.js");
14883
+ /* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__);
14884
+ // Imports
14885
+
14886
+
14887
+ var ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_sourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));
14888
+ // Module
14889
+ ___CSS_LOADER_EXPORT___.push([module.id, `/*
14890
+ * Copyright (c) Saga Inc.
14891
+ * Distributed under the terms of the GNU Affero General Public License v3.0 License.
14892
+ */
14893
+
14894
+
14895
+ .file-list {
14896
+ list-style: none;
14897
+ padding-left: 0;
14898
+ margin: 0;
14899
+ }
14900
+
14901
+ .file-list li {
14902
+ margin-bottom: 6px;
14903
+ }
14904
+
14905
+ .modal-footer {
14906
+ margin-top: 16px;
14907
+ display: flex;
14908
+ justify-content: flex-end;
14909
+ }
14910
+
14911
+ .files-selector-submit-button {
14912
+ margin-top: 8px;
14913
+ background-color: var(--purple-400) !important;
14914
+ color: var(--purple-700) !important;
14915
+ border: none !important;
14916
+ border-radius: 4px !important;
14917
+ font-weight: 500 !important;
14918
+ padding: 8px 16px !important;
14919
+ width: 100% !important;
14920
+ max-width: 100% !important;
14921
+ box-sizing: border-box !important;
14922
+ }
14923
+
14924
+ .files-selector-submit-button:hover {
14925
+ background-color: var(--purple-500) !important;
14926
+ }
14927
+
14928
+ .file-list input[type="checkbox"],
14929
+ .select-all input[type="checkbox"]{
14930
+ transform: scale(1.3);
14931
+ margin-right: 6px;
14932
+ accent-color: var(--purple-500);
14933
+ }
14934
+
14935
+ .file-list svg {
14936
+ color: grey;
14937
+ margin-right: 4px;
14938
+ vertical-align: middle;
14939
+ }
14940
+
14941
+ .select-all label {
14942
+ font-weight: 500;
14943
+ display: flex;
14944
+ align-items: center;
14945
+ gap: 6px;
14946
+ }
14947
+
14948
+ /* Modal header */
14949
+ .modal-header {
14950
+ display: flex;
14951
+ align-items: center;
14952
+ justify-content: space-between;
14953
+ gap: 8px;
14954
+ margin-bottom: 1px;
14955
+ }
14956
+
14957
+ .modal-title {
14958
+ margin: 0;
14959
+ font-size: 1.2rem;
14960
+ }
14961
+
14962
+
14963
+ .modal-subtext {
14964
+ font-size: 0.7rem;
14965
+ color: #555;
14966
+ margin: 0;
14967
+ font-style: italic;
14968
+ }
14969
+
14970
+ .modal-subheader{
14971
+ margin-bottom: 7px;
14972
+ }
14973
+
14974
+ /* Checkbox label for spacing */
14975
+ .checkbox-label {
14976
+ display: flex;
14977
+ align-items: center;
14978
+ gap: 6px;
14979
+ }
14980
+
14981
+ /* Scrollable file list */
14982
+ .file-list-scrollable {
14983
+ max-height: 300px;
14984
+ overflow-y: auto;
14985
+ margin-top: 8px;
14986
+ }
14987
+
14988
+ /* File list items */
14989
+ .file-list {
14990
+ list-style: none;
14991
+ padding-left: 0;
14992
+ margin: 0;
14993
+ }
14994
+
14995
+ /* Select all section */
14996
+ .files-selector-select-all {
14997
+ margin-bottom: 8px;
14998
+ }
14999
+ `, "",{"version":3,"sources":["webpack://./style/FilesSelector.css"],"names":[],"mappings":"AAAA;;;EAGE;;;AAGF;EACE,gBAAgB;EAChB,eAAe;EACf,SAAS;AACX;;AAEA;EACE,kBAAkB;AACpB;;AAEA;EACE,gBAAgB;EAChB,aAAa;EACb,yBAAyB;AAC3B;;AAEA;EACE,eAAe;EACf,8CAA8C;EAC9C,mCAAmC;EACnC,uBAAuB;EACvB,6BAA6B;EAC7B,2BAA2B;EAC3B,4BAA4B;EAC5B,sBAAsB;EACtB,0BAA0B;EAC1B,iCAAiC;AACnC;;AAEA;EACE,8CAA8C;AAChD;;AAEA;;EAEE,qBAAqB;EACrB,iBAAiB;EACjB,+BAA+B;AACjC;;AAEA;EACE,WAAW;EACX,iBAAiB;EACjB,sBAAsB;AACxB;;AAEA;EACE,gBAAgB;EAChB,aAAa;EACb,mBAAmB;EACnB,QAAQ;AACV;;AAEA,iBAAiB;AACjB;EACE,aAAa;EACb,mBAAmB;EACnB,8BAA8B;EAC9B,QAAQ;EACR,kBAAkB;AACpB;;AAEA;EACE,SAAS;EACT,iBAAiB;AACnB;;;AAGA;EACE,iBAAiB;EACjB,WAAW;EACX,SAAS;EACT,kBAAkB;AACpB;;AAEA;EACE,kBAAkB;AACpB;;AAEA,+BAA+B;AAC/B;EACE,aAAa;EACb,mBAAmB;EACnB,QAAQ;AACV;;AAEA,yBAAyB;AACzB;EACE,iBAAiB;EACjB,gBAAgB;EAChB,eAAe;AACjB;;AAEA,oBAAoB;AACpB;EACE,gBAAgB;EAChB,eAAe;EACf,SAAS;AACX;;AAEA,uBAAuB;AACvB;EACE,kBAAkB;AACpB","sourcesContent":["/*\n * Copyright (c) Saga Inc.\n * Distributed under the terms of the GNU Affero General Public License v3.0 License.\n */\n\n\n.file-list {\n list-style: none;\n padding-left: 0;\n margin: 0;\n}\n\n.file-list li {\n margin-bottom: 6px;\n}\n\n.modal-footer {\n margin-top: 16px;\n display: flex;\n justify-content: flex-end;\n}\n\n.files-selector-submit-button {\n margin-top: 8px;\n background-color: var(--purple-400) !important;\n color: var(--purple-700) !important;\n border: none !important;\n border-radius: 4px !important;\n font-weight: 500 !important;\n padding: 8px 16px !important;\n width: 100% !important;\n max-width: 100% !important;\n box-sizing: border-box !important;\n}\n\n.files-selector-submit-button:hover {\n background-color: var(--purple-500) !important;\n}\n\n.file-list input[type=\"checkbox\"],\n.select-all input[type=\"checkbox\"]{\n transform: scale(1.3);\n margin-right: 6px;\n accent-color: var(--purple-500);\n}\n\n.file-list svg {\n color: grey;\n margin-right: 4px;\n vertical-align: middle;\n}\n\n.select-all label {\n font-weight: 500;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n/* Modal header */\n.modal-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n margin-bottom: 1px;\n}\n\n.modal-title {\n margin: 0;\n font-size: 1.2rem;\n}\n\n\n.modal-subtext {\n font-size: 0.7rem;\n color: #555;\n margin: 0;\n font-style: italic;\n}\n\n.modal-subheader{\n margin-bottom: 7px;\n}\n\n/* Checkbox label for spacing */\n.checkbox-label {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n/* Scrollable file list */\n.file-list-scrollable {\n max-height: 300px;\n overflow-y: auto;\n margin-top: 8px;\n}\n\n/* File list items */\n.file-list {\n list-style: none;\n padding-left: 0;\n margin: 0;\n}\n\n/* Select all section */\n.files-selector-select-all {\n margin-bottom: 8px;\n}\n"],"sourceRoot":""}]);
15000
+ // Exports
15001
+ /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);
15002
+
15003
+
14244
15004
  /***/ }),
14245
15005
 
14246
15006
  /***/ "./node_modules/css-loader/dist/cjs.js!./style/IconButton.css":
@@ -15460,6 +16220,7 @@ ___CSS_LOADER_EXPORT___.push([module.id, `/*
15460
16220
  align-items: center;
15461
16221
  gap: 4px;
15462
16222
  padding: 8px 10px;
16223
+ overflow-x: hidden;
15463
16224
  }
15464
16225
 
15465
16226
  /* Consistent spacing for all children of context container */
@@ -15478,14 +16239,15 @@ ___CSS_LOADER_EXPORT___.push([module.id, `/*
15478
16239
 
15479
16240
  font-size: 12px;
15480
16241
  height: 20px;
15481
- width: fit-content;
16242
+ max-width: 100%;
16243
+ min-width: 0;
15482
16244
 
15483
16245
  border: 1px solid var(--jp-border-color1);
15484
16246
  cursor: pointer;
16247
+ }
15485
16248
 
15486
- &:hover {
15487
- background-color: var(--jp-layout-color3);
15488
- }
16249
+ .selected-context-container:hover {
16250
+ background-color: var(--jp-layout-color3);
15489
16251
  }
15490
16252
 
15491
16253
  .selected-context-container .rule-name {
@@ -15504,7 +16266,7 @@ ___CSS_LOADER_EXPORT___.push([module.id, `/*
15504
16266
  width: 12px;
15505
16267
  max-height: 14px;
15506
16268
  color: var(--jp-content-font-color3);
15507
- }`, "",{"version":3,"sources":["webpack://./style/SelectedContextContainer.css"],"names":[],"mappings":"AAAA;;;EAGE;;AAEF;EACE,aAAa;EACb,eAAe;EACf,mBAAmB;EACnB,QAAQ;EACR,iBAAiB;AACnB;;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,kBAAkB;;EAElB,yCAAyC;EACzC,eAAe;;EAEf;IACE,yCAAyC;EAC3C;AACF;;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}\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 width: fit-content;\n\n border: 1px solid var(--jp-border-color1);\n cursor: pointer;\n\n &:hover {\n background-color: var(--jp-layout-color3);\n }\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":""}]);
16269
+ }`, "",{"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":""}]);
15508
16270
  // Exports
15509
16271
  /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);
15510
16272
 
@@ -15627,6 +16389,65 @@ a {
15627
16389
  /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);
15628
16390
 
15629
16391
 
16392
+ /***/ }),
16393
+
16394
+ /***/ "./node_modules/css-loader/dist/cjs.js!./style/StreamlitPreviewPlugin.css":
16395
+ /*!********************************************************************************!*\
16396
+ !*** ./node_modules/css-loader/dist/cjs.js!./style/StreamlitPreviewPlugin.css ***!
16397
+ \********************************************************************************/
16398
+ /***/ ((module, __webpack_exports__, __webpack_require__) => {
16399
+
16400
+ __webpack_require__.r(__webpack_exports__);
16401
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
16402
+ /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
16403
+ /* harmony export */ });
16404
+ /* harmony import */ var _node_modules_css_loader_dist_runtime_sourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../node_modules/css-loader/dist/runtime/sourceMaps.js */ "./node_modules/css-loader/dist/runtime/sourceMaps.js");
16405
+ /* harmony import */ var _node_modules_css_loader_dist_runtime_sourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_sourceMaps_js__WEBPACK_IMPORTED_MODULE_0__);
16406
+ /* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../node_modules/css-loader/dist/runtime/api.js */ "./node_modules/css-loader/dist/runtime/api.js");
16407
+ /* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__);
16408
+ // Imports
16409
+
16410
+
16411
+ var ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_sourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));
16412
+ // Module
16413
+ ___CSS_LOADER_EXPORT___.push([module.id, `/*
16414
+ * Copyright (c) Saga Inc.
16415
+ * Distributed under the terms of the GNU Affero General Public License v3.0 License.
16416
+ */
16417
+
16418
+ .mito-deploy-button {
16419
+ display: flex !important;
16420
+ align-items: center !important;
16421
+ gap: 6px !important;
16422
+ padding: 4px 8px !important;
16423
+ color: var(--jp-ui-font-color1) !important;
16424
+ background-color: var(--jp-layout-color2) !important;
16425
+ }
16426
+
16427
+ .mito-deploy-button:hover {
16428
+ background-color: var(--jp-layout-color3) !important;
16429
+ }
16430
+
16431
+ .mito-deploy-button .mito-ai-deploy-icon {
16432
+ display: flex !important;
16433
+ align-items: center !important;
16434
+ height: 10px !important;
16435
+ width: 10px !important;
16436
+ font-size: 12px !important;
16437
+ }
16438
+
16439
+ .mito-deploy-button::slotted(svg),
16440
+ .mito-deploy-button svg {
16441
+ width: 12px !important;
16442
+ height: 12px !important;
16443
+ max-width: 12px !important;
16444
+ max-height: 12px !important;
16445
+ margin-right: 4px !important;
16446
+ }`, "",{"version":3,"sources":["webpack://./style/StreamlitPreviewPlugin.css"],"names":[],"mappings":"AAAA;;;EAGE;;AAEF;IACI,wBAAwB;IACxB,8BAA8B;IAC9B,mBAAmB;IACnB,2BAA2B;IAC3B,0CAA0C;IAC1C,oDAAoD;AACxD;;AAEA;IACI,oDAAoD;AACxD;;AAEA;IACI,wBAAwB;IACxB,8BAA8B;IAC9B,uBAAuB;IACvB,sBAAsB;IACtB,0BAA0B;AAC9B;;AAEA;;IAEI,sBAAsB;IACtB,uBAAuB;IACvB,0BAA0B;IAC1B,2BAA2B;IAC3B,4BAA4B;AAChC","sourcesContent":["/*\n * Copyright (c) Saga Inc.\n * Distributed under the terms of the GNU Affero General Public License v3.0 License.\n */\n\n.mito-deploy-button {\n display: flex !important;\n align-items: center !important;\n gap: 6px !important;\n padding: 4px 8px !important;\n color: var(--jp-ui-font-color1) !important;\n background-color: var(--jp-layout-color2) !important;\n}\n\n.mito-deploy-button:hover {\n background-color: var(--jp-layout-color3) !important;\n}\n\n.mito-deploy-button .mito-ai-deploy-icon {\n display: flex !important;\n align-items: center !important;\n height: 10px !important;\n width: 10px !important;\n font-size: 12px !important;\n}\n\n.mito-deploy-button::slotted(svg),\n.mito-deploy-button svg {\n width: 12px !important;\n height: 12px !important;\n max-width: 12px !important;\n max-height: 12px !important;\n margin-right: 4px !important;\n}"],"sourceRoot":""}]);
16447
+ // Exports
16448
+ /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);
16449
+
16450
+
15630
16451
  /***/ }),
15631
16452
 
15632
16453
  /***/ "./node_modules/css-loader/dist/cjs.js!./style/TextAndIconButton.css":
@@ -15904,6 +16725,16 @@ ___CSS_LOADER_EXPORT___.push([module.id, `/*
15904
16725
  /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);
15905
16726
 
15906
16727
 
16728
+ /***/ }),
16729
+
16730
+ /***/ "./src/icons/App/DeployIcon.svg":
16731
+ /*!**************************************!*\
16732
+ !*** ./src/icons/App/DeployIcon.svg ***!
16733
+ \**************************************/
16734
+ /***/ ((module) => {
16735
+
16736
+ module.exports = "<svg width=\"1298\" height=\"1286\" viewBox=\"0 0 1298 1286\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g fill=\"currentColor\">\n <path d=\"M689.8 1007.36C644.524 1028.32 598.8 1047.93 552.76 1066.2L569.733 1285.77C638.785 1254.45 799 1157.24 926.04 893.279C871.201 922.393 816.352 948.581 769.52 970.929C743.254 983.518 716.602 995.58 689.806 1007.36L689.8 1007.36Z\" />\n <path d=\"M815.76 382.387C791.224 382.387 766.698 391.626 748.02 410.084C729.994 427.923 720.056 451.62 720.056 476.824C720.056 502.021 729.983 525.725 748.029 543.564C785.379 580.501 846.166 580.491 883.496 543.564C883.496 543.554 883.507 543.554 883.507 543.554C901.533 525.715 911.48 502.018 911.48 476.814C911.48 451.616 901.542 427.912 883.507 410.073C864.84 391.615 840.304 382.385 815.761 382.385L815.76 382.387Z\" />\n <path d=\"M349.453 462.747C364.328 432.924 380.213 401.747 397.229 370.408C130.563 495.835 32.0558 654.008 0.21582 722.461L220.562 739.112C243.614 682.175 268.75 625.664 296.073 569.925C312.661 535.961 330.401 499.685 349.448 462.748L349.453 462.747Z\" />\n <path d=\"M914.027 33.9479L1263.4 379.428C1280.5 311.901 1289.8 244.215 1294.2 180.815C1294.57 175.502 1294.94 170.2 1295.24 164.841C1295.7 156.815 1296.08 148.893 1296.39 141.029C1296.74 132.003 1297.02 122.915 1297.19 113.789C1297.32 107.513 1297.42 101.3 1297.45 95.1639C1297.53 82.6117 1297.5 70.0025 1297.27 57.2892C1297.21 54.4143 1297.14 51.6017 1297.07 48.7632C1296.68 33.4872 1296.14 18.1379 1295.28 2.66453C1193.44 -3.4552 1054.16 -1.29387 914.028 33.9565L914.027 33.9479Z\" />\n <path d=\"M1106.33 687.12C1113.39 679.36 1120.28 671.423 1126.96 663.235C1127.83 662.162 1128.78 661.11 1129.65 660.021C1136.68 651.261 1143.42 642.172 1150.03 632.933C1152.32 629.735 1154.57 626.506 1156.79 623.272C1161.92 615.824 1166.89 608.209 1171.74 600.46C1174.87 595.46 1177.89 590.408 1180.87 585.345C1184.4 579.345 1187.85 573.272 1191.24 567.105C1194.19 561.694 1197.13 556.282 1199.93 550.802C1202.02 546.729 1203.99 542.542 1206.02 538.401C1211.38 527.391 1216.53 516.287 1221.32 505.079C1222.07 503.318 1222.81 501.542 1223.56 499.766C1232.09 479.354 1239.68 458.667 1246.47 437.829L855.11 50.802C755.386 82.99 670.87 130.214 602.99 191.362C601.24 192.935 599.49 194.523 597.751 196.122C588.876 204.31 580.215 212.685 571.939 221.362C569.001 224.461 566.163 227.748 563.277 230.951C497.903 303.211 443.179 397.524 396.451 488.218C386.039 509.119 376.139 529.354 366.951 548.182C330.524 622.468 297.377 699.395 268.399 776.848C266.362 782.312 262.612 786.697 257.961 789.734C237.472 842.307 218.81 895.171 202.3 948.107L340.153 1084.43C395.164 1067.65 450.101 1048.65 504.7 1027.74C507.538 1024.61 510.887 1021.9 515.075 1020.37C566.689 1001.51 618.023 980.661 668.621 958.427C678.861 953.677 689.111 948.953 699.299 944.062C828.601 882.912 975.019 813.661 1075.33 718.903C1083.84 710.892 1092.02 702.491 1100.07 693.929C1102.19 691.669 1104.26 689.393 1106.34 687.122L1106.33 687.12ZM921.187 581.344C892.114 610.104 853.911 624.48 815.723 624.48C777.535 624.48 739.348 610.105 710.275 581.355C682.051 553.443 666.515 516.328 666.515 476.828C666.515 437.328 682.067 400.213 710.264 372.301C768.426 314.791 863.038 314.812 921.171 372.291C949.411 400.203 964.947 437.318 964.947 476.818C964.947 516.307 949.406 553.432 921.182 581.344L921.187 581.344Z\" />\n <path d=\"M147.088 1138.72L198.905 982.058L302.981 1084.64L147.088 1138.72Z\" />\n </g>\n</svg>\n";
16737
+
15907
16738
  /***/ }),
15908
16739
 
15909
16740
  /***/ "./src/icons/AppBuilderExcludeCellIcon.svg":
@@ -16936,6 +17767,60 @@ var update = _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js
16936
17767
  /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_node_modules_css_loader_dist_cjs_js_ErrorMimeRendererPlugin_css__WEBPACK_IMPORTED_MODULE_6__["default"] && _node_modules_css_loader_dist_cjs_js_ErrorMimeRendererPlugin_css__WEBPACK_IMPORTED_MODULE_6__["default"].locals ? _node_modules_css_loader_dist_cjs_js_ErrorMimeRendererPlugin_css__WEBPACK_IMPORTED_MODULE_6__["default"].locals : undefined);
16937
17768
 
16938
17769
 
17770
+ /***/ }),
17771
+
17772
+ /***/ "./style/FilesSelector.css":
17773
+ /*!*********************************!*\
17774
+ !*** ./style/FilesSelector.css ***!
17775
+ \*********************************/
17776
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
17777
+
17778
+ __webpack_require__.r(__webpack_exports__);
17779
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
17780
+ /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
17781
+ /* harmony export */ });
17782
+ /* harmony import */ var _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! !../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js */ "./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js");
17783
+ /* harmony import */ var _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0__);
17784
+ /* harmony import */ var _node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! !../node_modules/style-loader/dist/runtime/styleDomAPI.js */ "./node_modules/style-loader/dist/runtime/styleDomAPI.js");
17785
+ /* harmony import */ var _node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1__);
17786
+ /* harmony import */ var _node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! !../node_modules/style-loader/dist/runtime/insertBySelector.js */ "./node_modules/style-loader/dist/runtime/insertBySelector.js");
17787
+ /* harmony import */ var _node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2__);
17788
+ /* harmony import */ var _node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! !../node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js */ "./node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js");
17789
+ /* harmony import */ var _node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3__);
17790
+ /* harmony import */ var _node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! !../node_modules/style-loader/dist/runtime/insertStyleElement.js */ "./node_modules/style-loader/dist/runtime/insertStyleElement.js");
17791
+ /* harmony import */ var _node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4__);
17792
+ /* harmony import */ var _node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! !../node_modules/style-loader/dist/runtime/styleTagTransform.js */ "./node_modules/style-loader/dist/runtime/styleTagTransform.js");
17793
+ /* harmony import */ var _node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5__);
17794
+ /* harmony import */ var _node_modules_css_loader_dist_cjs_js_FilesSelector_css__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! !!../node_modules/css-loader/dist/cjs.js!./FilesSelector.css */ "./node_modules/css-loader/dist/cjs.js!./style/FilesSelector.css");
17795
+
17796
+
17797
+
17798
+
17799
+
17800
+
17801
+
17802
+
17803
+
17804
+
17805
+
17806
+ var options = {};
17807
+
17808
+ options.styleTagTransform = (_node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5___default());
17809
+ options.setAttributes = (_node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3___default());
17810
+
17811
+ options.insert = _node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2___default().bind(null, "head");
17812
+
17813
+ options.domAPI = (_node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1___default());
17814
+ options.insertStyleElement = (_node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4___default());
17815
+
17816
+ var update = _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0___default()(_node_modules_css_loader_dist_cjs_js_FilesSelector_css__WEBPACK_IMPORTED_MODULE_6__["default"], options);
17817
+
17818
+
17819
+
17820
+
17821
+ /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_node_modules_css_loader_dist_cjs_js_FilesSelector_css__WEBPACK_IMPORTED_MODULE_6__["default"] && _node_modules_css_loader_dist_cjs_js_FilesSelector_css__WEBPACK_IMPORTED_MODULE_6__["default"].locals ? _node_modules_css_loader_dist_cjs_js_FilesSelector_css__WEBPACK_IMPORTED_MODULE_6__["default"].locals : undefined);
17822
+
17823
+
16939
17824
  /***/ }),
16940
17825
 
16941
17826
  /***/ "./style/IconButton.css":
@@ -17530,6 +18415,60 @@ var update = _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js
17530
18415
  /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_node_modules_css_loader_dist_cjs_js_SettingsWidget_css__WEBPACK_IMPORTED_MODULE_6__["default"] && _node_modules_css_loader_dist_cjs_js_SettingsWidget_css__WEBPACK_IMPORTED_MODULE_6__["default"].locals ? _node_modules_css_loader_dist_cjs_js_SettingsWidget_css__WEBPACK_IMPORTED_MODULE_6__["default"].locals : undefined);
17531
18416
 
17532
18417
 
18418
+ /***/ }),
18419
+
18420
+ /***/ "./style/StreamlitPreviewPlugin.css":
18421
+ /*!******************************************!*\
18422
+ !*** ./style/StreamlitPreviewPlugin.css ***!
18423
+ \******************************************/
18424
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
18425
+
18426
+ __webpack_require__.r(__webpack_exports__);
18427
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
18428
+ /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
18429
+ /* harmony export */ });
18430
+ /* harmony import */ var _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! !../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js */ "./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js");
18431
+ /* harmony import */ var _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0__);
18432
+ /* harmony import */ var _node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! !../node_modules/style-loader/dist/runtime/styleDomAPI.js */ "./node_modules/style-loader/dist/runtime/styleDomAPI.js");
18433
+ /* harmony import */ var _node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1__);
18434
+ /* harmony import */ var _node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! !../node_modules/style-loader/dist/runtime/insertBySelector.js */ "./node_modules/style-loader/dist/runtime/insertBySelector.js");
18435
+ /* harmony import */ var _node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2__);
18436
+ /* harmony import */ var _node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! !../node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js */ "./node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js");
18437
+ /* harmony import */ var _node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3__);
18438
+ /* harmony import */ var _node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! !../node_modules/style-loader/dist/runtime/insertStyleElement.js */ "./node_modules/style-loader/dist/runtime/insertStyleElement.js");
18439
+ /* harmony import */ var _node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4__);
18440
+ /* harmony import */ var _node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! !../node_modules/style-loader/dist/runtime/styleTagTransform.js */ "./node_modules/style-loader/dist/runtime/styleTagTransform.js");
18441
+ /* harmony import */ var _node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5__);
18442
+ /* harmony import */ var _node_modules_css_loader_dist_cjs_js_StreamlitPreviewPlugin_css__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! !!../node_modules/css-loader/dist/cjs.js!./StreamlitPreviewPlugin.css */ "./node_modules/css-loader/dist/cjs.js!./style/StreamlitPreviewPlugin.css");
18443
+
18444
+
18445
+
18446
+
18447
+
18448
+
18449
+
18450
+
18451
+
18452
+
18453
+
18454
+ var options = {};
18455
+
18456
+ options.styleTagTransform = (_node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5___default());
18457
+ options.setAttributes = (_node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3___default());
18458
+
18459
+ options.insert = _node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2___default().bind(null, "head");
18460
+
18461
+ options.domAPI = (_node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1___default());
18462
+ options.insertStyleElement = (_node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4___default());
18463
+
18464
+ var update = _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0___default()(_node_modules_css_loader_dist_cjs_js_StreamlitPreviewPlugin_css__WEBPACK_IMPORTED_MODULE_6__["default"], options);
18465
+
18466
+
18467
+
18468
+
18469
+ /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_node_modules_css_loader_dist_cjs_js_StreamlitPreviewPlugin_css__WEBPACK_IMPORTED_MODULE_6__["default"] && _node_modules_css_loader_dist_cjs_js_StreamlitPreviewPlugin_css__WEBPACK_IMPORTED_MODULE_6__["default"].locals ? _node_modules_css_loader_dist_cjs_js_StreamlitPreviewPlugin_css__WEBPACK_IMPORTED_MODULE_6__["default"].locals : undefined);
18470
+
18471
+
17533
18472
  /***/ }),
17534
18473
 
17535
18474
  /***/ "./style/TextAndIconButton.css":
@@ -17749,4 +18688,4 @@ var update = _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js
17749
18688
  /***/ })
17750
18689
 
17751
18690
  }]);
17752
- //# sourceMappingURL=lib_index_js.81703ac2bc645e5c2fc2.js.map
18691
+ //# sourceMappingURL=lib_index_js.0c3368195d954d2ed033.js.map