sage-agent-internal 0.2.6__tar.gz → 0.2.8__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (225) hide show
  1. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/PKG-INFO +2 -4
  2. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/package.json +2 -9
  3. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/sage_agent_internal/_version.py +1 -1
  4. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/sage_agent_internal/labextension/package.json +3 -10
  5. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/sage_agent_internal/labextension/schemas/sage-agent-internal/package.json.orig +2 -9
  6. sage_agent_internal-0.2.6/sage_agent_internal/labextension/static/remoteEntry.4a1093a43fdce6a4f6e0.js → sage_agent_internal-0.2.8/sage_agent_internal/labextension/static/remoteEntry.753494b5ce20b160502b.js +1 -1
  7. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/ui-tests/playwright.config.js +3 -0
  8. sage_agent_internal-0.2.8/ui-tests/slack-test-README.md +44 -0
  9. sage_agent_internal-0.2.8/ui-tests/test_slack.py +245 -0
  10. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/.copier-answers.yml +0 -0
  11. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/.gitignore +0 -0
  12. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/.keep +0 -0
  13. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/.prettierignore +0 -0
  14. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/.vscode/settings.json +0 -0
  15. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/.yarnrc.yml +0 -0
  16. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/CHANGELOG.md +0 -0
  17. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/CLAUDE.md +0 -0
  18. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/LICENSE +0 -0
  19. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/README.md +0 -0
  20. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/RELEASE.md +0 -0
  21. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/__tests__/sage_agent.spec.ts +0 -0
  22. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/babel.config.js +0 -0
  23. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/cli-chat-tool/index.ts +0 -0
  24. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/cli-chat-tool/package-lock.json +0 -0
  25. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/cli-chat-tool/package.json +0 -0
  26. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/cli-chat-tool/tsconfig.json +0 -0
  27. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/cli-chat-tool/yarn.lock +0 -0
  28. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/install.json +0 -0
  29. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/jest.config.js +0 -0
  30. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/package-lock.json +0 -0
  31. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/pyproject.toml +0 -0
  32. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/sage_agent_internal/__init__.py +0 -0
  33. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/sage_agent_internal/labextension/schemas/sage-agent-internal/plugin.json +0 -0
  34. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/sage_agent_internal/labextension/static/122.3c2c200586e65203b674.js +0 -0
  35. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/sage_agent_internal/labextension/static/220.d384edfd5bbcfda33a2a.js +0 -0
  36. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/sage_agent_internal/labextension/static/262.3fc4ad88e6f8c273d4ad.js +0 -0
  37. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/sage_agent_internal/labextension/static/353.2c285601a208c3735929.js +0 -0
  38. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/sage_agent_internal/labextension/static/363.6fc8d18eedbf137940f2.js +0 -0
  39. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/sage_agent_internal/labextension/static/364.c2fb82c6f484097228c6.js +0 -0
  40. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/sage_agent_internal/labextension/static/439.3cb9ac7022c8a6074647.js +0 -0
  41. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/sage_agent_internal/labextension/static/481.96b91d018df31d54d173.js +0 -0
  42. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/sage_agent_internal/labextension/static/553.b7906877d98a62265533.js +0 -0
  43. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/sage_agent_internal/labextension/static/553.b7906877d98a62265533.js.LICENSE.txt +0 -0
  44. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/sage_agent_internal/labextension/static/635.8c395c854aa2b140b668.js +0 -0
  45. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/sage_agent_internal/labextension/static/713.103cb5ae248be385b08a.js +0 -0
  46. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/sage_agent_internal/labextension/static/742.b204789055ded4e07883.js +0 -0
  47. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/sage_agent_internal/labextension/static/747.b8e9485ebcbb3066eb4b.js +0 -0
  48. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/sage_agent_internal/labextension/static/821.b58f29814f5900f1f6f8.js +0 -0
  49. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/sage_agent_internal/labextension/static/845.cc2bc80fbfea6d20a396.js +0 -0
  50. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/sage_agent_internal/labextension/static/888.09382cc93a2ad3932b31.js +0 -0
  51. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/sage_agent_internal/labextension/static/968.980219bfdaa6b20f56cb.js +0 -0
  52. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/sage_agent_internal/labextension/static/973.016a586759b281b79f91.js +0 -0
  53. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/sage_agent_internal/labextension/static/973.016a586759b281b79f91.js.LICENSE.txt +0 -0
  54. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/sage_agent_internal/labextension/static/style.js +0 -0
  55. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/sage_agent_internal/labextension/static/third-party-licenses.json +0 -0
  56. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/schema/plugin.json +0 -0
  57. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/setup.py +0 -0
  58. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/AppState.ts +0 -0
  59. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/BackendTools/DatabaseTools.ts +0 -0
  60. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/BackendTools/FilesystemTools.ts +0 -0
  61. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/BackendTools/WebTools.ts +0 -0
  62. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/BackendTools/index.ts +0 -0
  63. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/BackendTools/tickers.json +0 -0
  64. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/CellTrackingService.ts +0 -0
  65. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Chat/ActionHistory.ts +0 -0
  66. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Chat/ChatContextMenu/ChatContextLoaders.ts +0 -0
  67. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Chat/ChatContextMenu/ChatContextMenu.ts +0 -0
  68. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Chat/ChatContextMenu/ChatContextMenuLogic.ts +0 -0
  69. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Chat/ChatContextMenu/ChatContextMenuUtils.ts +0 -0
  70. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Chat/ChatContextMenu/ContextCacheService.ts +0 -0
  71. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Chat/ChatContextMenu/ContextCellHighlighter.ts +0 -0
  72. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Chat/ChatContextMenu/KernelExecutionListener.ts +0 -0
  73. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Chat/ChatContextMenu/icons.ts +0 -0
  74. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Chat/ChatHistoryManager.ts +0 -0
  75. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Chat/ChatInputManager.ts +0 -0
  76. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Chat/ChatMessages.ts +0 -0
  77. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Chat/ChatUIHelper.ts +0 -0
  78. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Chat/ConversationService.ts +0 -0
  79. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Chat/ConversationServiceUtils.ts +0 -0
  80. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Chat/RichTextChatInput.ts +0 -0
  81. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/CodebaseManager.ts +0 -0
  82. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Components/ChatboxContext.ts +0 -0
  83. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Components/CodeConfirmationDialog.ts +0 -0
  84. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Components/DiffApprovalDialog.ts +0 -0
  85. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Components/DiffNavigationContent.tsx +0 -0
  86. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Components/DiffNavigationWidget.tsx +0 -0
  87. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Components/InlineCompletionWidget.tsx +0 -0
  88. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Components/LLMStateDisplay/DiffItem.tsx +0 -0
  89. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Components/LLMStateDisplay/LLMStateContent.tsx +0 -0
  90. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Components/LLMStateDisplay/LLMStateDisplay.tsx +0 -0
  91. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Components/LLMStateDisplay/icons.ts +0 -0
  92. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Components/LLMStateDisplay/index.ts +0 -0
  93. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Components/LLMStateDisplay/types.ts +0 -0
  94. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Components/MoreOptionsDisplay.tsx +0 -0
  95. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Components/NewChatDisplayWidget.ts +0 -0
  96. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Components/PlanStateDisplay.tsx +0 -0
  97. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Components/RejectionFeedbackDialog.ts +0 -0
  98. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Components/Settings/SettingsWidget.tsx +0 -0
  99. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Components/SnippetCreationWidget/SnippetCreationContent.tsx +0 -0
  100. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Components/SnippetCreationWidget/SnippetCreationWidget.tsx +0 -0
  101. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Components/SnippetCreationWidget/SnippetForm.tsx +0 -0
  102. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Components/SnippetCreationWidget/SnippetFormModal.tsx +0 -0
  103. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Components/SnippetCreationWidget/SnippetList.tsx +0 -0
  104. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Components/SnippetCreationWidget/index.ts +0 -0
  105. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Components/SnippetCreationWidget/types.ts +0 -0
  106. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Components/UpdateBanner/UpdateBannerWidget.tsx +0 -0
  107. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Components/chatbox.ts +0 -0
  108. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Components/icons.ts +0 -0
  109. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Config/ConfigService.ts +0 -0
  110. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Config/models.json +0 -0
  111. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Config/optional_env.json +0 -0
  112. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Config/prompts/claude_system_prompt.md +0 -0
  113. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Config/prompts/claude_system_prompt_ask_mode.md +0 -0
  114. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Config/prompts/claude_system_prompt_edit_full_cell.md +0 -0
  115. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Config/prompts/claude_system_prompt_edit_selection.md +0 -0
  116. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Config/prompts/claude_system_prompt_fast_mode.md +0 -0
  117. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Config/tools.json +0 -0
  118. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Notebook/InlineDiffService.ts +0 -0
  119. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Notebook/NotebookCellTools.ts +0 -0
  120. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Notebook/NotebookChatContainer.ts +0 -0
  121. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Notebook/NotebookContextManager.ts +0 -0
  122. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Notebook/NotebookDiffManager.ts +0 -0
  123. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Notebook/NotebookDiffTools.ts +0 -0
  124. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Notebook/NotebookStateService.ts +0 -0
  125. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Notebook/NotebookTools.ts +0 -0
  126. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Notebook/WaitingUserReplyBoxManager.ts +0 -0
  127. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/NotebookSettingsContainer.ts +0 -0
  128. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Services/AnthropicMessageCreator.ts +0 -0
  129. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Services/AnthropicService.ts +0 -0
  130. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Services/AnthropicStreamHandler.ts +0 -0
  131. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Services/CompletionManager.ts +0 -0
  132. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Services/ContextService.ts +0 -0
  133. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Services/DatabaseMetadataCache.ts +0 -0
  134. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Services/DiffStateService.ts +0 -0
  135. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Services/IChatService.ts +0 -0
  136. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Services/NotebookCellStateService.ts +0 -0
  137. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Services/ServiceFactory.ts +0 -0
  138. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Services/ServiceUtils.ts +0 -0
  139. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Services/TabCompletionService.ts +0 -0
  140. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/Services/ToolService.ts +0 -0
  141. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/ThreadManager.ts +0 -0
  142. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/TrackingIDUtility.ts +0 -0
  143. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/commands.ts +0 -0
  144. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/eval_commands.ts +0 -0
  145. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/index.ts +0 -0
  146. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/plugin.ts +0 -0
  147. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/types/json.d.ts +0 -0
  148. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/types.ts +0 -0
  149. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/utils/VariableExtractor.ts +0 -0
  150. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/utils/caching.ts +0 -0
  151. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/utils/contextTagUtils.ts +0 -0
  152. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/utils/kernelPreview.ts +0 -0
  153. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/utils/kernelUtils.ts +0 -0
  154. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/utils/stateDBCaching.ts +0 -0
  155. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/utils/tokenUtils.ts +0 -0
  156. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/utils/toolDisplay.ts +0 -0
  157. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/src/utils.ts +0 -0
  158. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/base.css +0 -0
  159. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/chat-container.css +0 -0
  160. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/chat-mention-dropdown.css +0 -0
  161. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/code-mirror-merge.css +0 -0
  162. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/codebase-manager.css +0 -0
  163. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/diff-approval.css +0 -0
  164. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/diff-edit-mode.css +0 -0
  165. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/diff-mode.css +0 -0
  166. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/diff-navigation.css +0 -0
  167. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/floating-bottom-widget.css +0 -0
  168. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/fonts.css +0 -0
  169. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/icons/chat_input/agent-mode-shiny.svg +0 -0
  170. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/icons/chat_input/agent-mode.svg +0 -0
  171. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/icons/chat_input/approve.svg +0 -0
  172. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/icons/chat_input/arrow-down.svg +0 -0
  173. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/icons/chat_input/arrow-up.svg +0 -0
  174. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/icons/chat_input/ask-mode.svg +0 -0
  175. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/icons/chat_input/check.svg +0 -0
  176. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/icons/chat_input/dashed-circle.svg +0 -0
  177. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/icons/chat_input/hands-on-mode.svg +0 -0
  178. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/icons/chat_input/open.svg +0 -0
  179. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/icons/chat_input/reapply.svg +0 -0
  180. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/icons/chat_input/reject.svg +0 -0
  181. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/icons/chat_input/run.svg +0 -0
  182. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/icons/chat_input/search.svg +0 -0
  183. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/icons/chat_input/send.svg +0 -0
  184. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/icons/chat_input/stop.svg +0 -0
  185. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/icons/context_menu/cell.svg +0 -0
  186. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/icons/context_menu/data.svg +0 -0
  187. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/icons/context_menu/insert.svg +0 -0
  188. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/icons/context_menu/search.svg +0 -0
  189. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/icons/context_menu/snippets.svg +0 -0
  190. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/icons/context_menu/variable.svg +0 -0
  191. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/icons/state_display/menu-close.svg +0 -0
  192. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/icons/state_display/menu-icon.svg +0 -0
  193. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/icons/state_display/run_cell.svg +0 -0
  194. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/index.css +0 -0
  195. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/index.js +0 -0
  196. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/inline-diff-approval.css +0 -0
  197. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/left-side-menu.css +0 -0
  198. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/llm-state-display.css +0 -0
  199. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/minus-icon.css +0 -0
  200. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/modal.css +0 -0
  201. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/mode-selector-dropdown.css +0 -0
  202. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/more-options.css +0 -0
  203. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/new-chat-display.css +0 -0
  204. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/plan-state-display.css +0 -0
  205. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/settings-widget.css +0 -0
  206. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/snippet-creation.css +0 -0
  207. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/style.css +0 -0
  208. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/tab-completion.css +0 -0
  209. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/style/update-banner.css +0 -0
  210. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/templates/rule.example.md +0 -0
  211. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/tsconfig.json +0 -0
  212. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/tsconfig.test.json +0 -0
  213. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/ui-tests/README.md +0 -0
  214. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/ui-tests/jupyter_server_test_config.py +0 -0
  215. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/ui-tests/package.json +0 -0
  216. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/ui-tests/setup-tests.bat +0 -0
  217. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/ui-tests/setup-tests.sh +0 -0
  218. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/ui-tests/tests/README_SAGE_LLM_TESTS.md +0 -0
  219. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/ui-tests/tests/SAGE_LLM_TESTING_PLAN.md +0 -0
  220. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/ui-tests/tests/config-example.ts +0 -0
  221. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/ui-tests/tests/sage_agent.spec.ts +0 -0
  222. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/ui-tests/tests/sage_diff_interactions.spec.ts +0 -0
  223. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/ui-tests/tests/sage_llm_test.spec.ts +0 -0
  224. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/ui-tests/yarn.lock +0 -0
  225. {sage_agent_internal-0.2.6 → sage_agent_internal-0.2.8}/yarn.lock +0 -0
@@ -1,10 +1,8 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sage_agent_internal
3
- Version: 0.2.6
3
+ Version: 0.2.8
4
4
  Summary: Sage Agent - Your Jupyter Notebook Assistant
5
- Project-URL: Homepage, https://github.com/AlpineX-Labs/jupyter-sage-agent-internal
6
- Project-URL: Bug Tracker, https://github.com/AlpineX-Labs/jupyter-sage-agent-internal/issues
7
- Project-URL: Repository, https://github.com/AlpineX-Labs/jupyter-sage-agent-internal.git
5
+ Project-URL: Homepage, https://sagebook.ai/
8
6
  Author-email: Daniel Schaffield <danielschaffield@gmail.com>
9
7
  License: BSD 3-Clause License
10
8
 
@@ -1,16 +1,13 @@
1
1
  {
2
2
  "name": "sage-agent-internal",
3
- "version": "0.2.6",
3
+ "version": "0.2.8",
4
4
  "description": "Sage Agent - Your Jupyter Notebook Assistant",
5
5
  "keywords": [
6
6
  "jupyter",
7
7
  "jupyterlab",
8
8
  "jupyterlab-extension"
9
9
  ],
10
- "homepage": "https://github.com/AlpineX-Labs/jupyter-sage-agent-internal",
11
- "bugs": {
12
- "url": "https://github.com/AlpineX-Labs/jupyter-sage-agent-internal/issues"
13
- },
10
+ "homepage": "https://sagebook.ai/",
14
11
  "license": "BSD-3-Clause",
15
12
  "author": {
16
13
  "name": "Daniel Schaffield",
@@ -25,10 +22,6 @@
25
22
  "main": "lib/index.js",
26
23
  "types": "lib/index.d.ts",
27
24
  "style": "style/index.css",
28
- "repository": {
29
- "type": "git",
30
- "url": "https://github.com/AlpineX-Labs/jupyter-sage-agent-internal.git"
31
- },
32
25
  "scripts": {
33
26
  "build": "jlpm prebuild && jlpm build:lib && jlpm build:labextension:dev",
34
27
  "build:prod": "jlpm prebuild && jlpm clean && jlpm build:lib:prod && jlpm build:labextension",
@@ -1,4 +1,4 @@
1
1
  # This file is auto-generated by Hatchling. As such, do not:
2
2
  # - modify
3
3
  # - track in version control e.g. be sure to add to .gitignore
4
- __version__ = VERSION = '0.2.6'
4
+ __version__ = VERSION = '0.2.8'
@@ -1,16 +1,13 @@
1
1
  {
2
2
  "name": "sage-agent-internal",
3
- "version": "0.2.6",
3
+ "version": "0.2.8",
4
4
  "description": "Sage Agent - Your Jupyter Notebook Assistant",
5
5
  "keywords": [
6
6
  "jupyter",
7
7
  "jupyterlab",
8
8
  "jupyterlab-extension"
9
9
  ],
10
- "homepage": "https://github.com/AlpineX-Labs/jupyter-sage-agent-internal",
11
- "bugs": {
12
- "url": "https://github.com/AlpineX-Labs/jupyter-sage-agent-internal/issues"
13
- },
10
+ "homepage": "https://sagebook.ai/",
14
11
  "license": "BSD-3-Clause",
15
12
  "author": {
16
13
  "name": "Daniel Schaffield",
@@ -25,10 +22,6 @@
25
22
  "main": "lib/index.js",
26
23
  "types": "lib/index.d.ts",
27
24
  "style": "style/index.css",
28
- "repository": {
29
- "type": "git",
30
- "url": "https://github.com/AlpineX-Labs/jupyter-sage-agent-internal.git"
31
- },
32
25
  "scripts": {
33
26
  "build": "jlpm prebuild && jlpm build:lib && jlpm build:labextension:dev",
34
27
  "build:prod": "jlpm prebuild && jlpm clean && jlpm build:lib:prod && jlpm build:labextension",
@@ -127,7 +120,7 @@
127
120
  "outputDir": "sage_agent_internal/labextension",
128
121
  "schemaDir": "schema",
129
122
  "_build": {
130
- "load": "static/remoteEntry.4a1093a43fdce6a4f6e0.js",
123
+ "load": "static/remoteEntry.753494b5ce20b160502b.js",
131
124
  "extension": "./extension",
132
125
  "style": "./style"
133
126
  }
@@ -1,16 +1,13 @@
1
1
  {
2
2
  "name": "sage-agent-internal",
3
- "version": "0.2.6",
3
+ "version": "0.2.8",
4
4
  "description": "Sage Agent - Your Jupyter Notebook Assistant",
5
5
  "keywords": [
6
6
  "jupyter",
7
7
  "jupyterlab",
8
8
  "jupyterlab-extension"
9
9
  ],
10
- "homepage": "https://github.com/AlpineX-Labs/jupyter-sage-agent-internal",
11
- "bugs": {
12
- "url": "https://github.com/AlpineX-Labs/jupyter-sage-agent-internal/issues"
13
- },
10
+ "homepage": "https://sagebook.ai/",
14
11
  "license": "BSD-3-Clause",
15
12
  "author": {
16
13
  "name": "Daniel Schaffield",
@@ -25,10 +22,6 @@
25
22
  "main": "lib/index.js",
26
23
  "types": "lib/index.d.ts",
27
24
  "style": "style/index.css",
28
- "repository": {
29
- "type": "git",
30
- "url": "https://github.com/AlpineX-Labs/jupyter-sage-agent-internal.git"
31
- },
32
25
  "scripts": {
33
26
  "build": "jlpm prebuild && jlpm build:lib && jlpm build:labextension:dev",
34
27
  "build:prod": "jlpm prebuild && jlpm clean && jlpm build:lib:prod && jlpm build:labextension",
@@ -1 +1 @@
1
- var _JUPYTERLAB;(()=>{"use strict";var e,r,t,a,n,o,i,f,d,l,u,c,s,p,h,b,m,g,v,y,j,w,P,k,S,O={484:(e,r,t)=>{var a={"./index":()=>Promise.all([t.e(353),t.e(747),t.e(122),t.e(973),t.e(760),t.e(345),t.e(379),t.e(839),t.e(968)]).then(()=>()=>t(9040)),"./extension":()=>Promise.all([t.e(353),t.e(747),t.e(122),t.e(973),t.e(760),t.e(345),t.e(379),t.e(839),t.e(968)]).then(()=>()=>t(9040)),"./style":()=>t.e(363).then(()=>()=>t(8363))},n=(e,r)=>(t.R=r,r=t.o(a,e)?a[e]():Promise.resolve().then(()=>{throw new Error('Module "'+e+'" does not exist in container.')}),t.R=void 0,r),o=(e,r)=>{if(t.S){var a="default",n=t.S[a];if(n&&n!==e)throw new Error("Container initialization failed as it has already been initialized with a different share scope");return t.S[a]=e,t.I(a,r)}};t.d(r,{get:()=>n,init:()=>o})}},x={};function _(e){var r=x[e];if(void 0!==r)return r.exports;var t=x[e]={id:e,exports:{}};return O[e].call(t.exports,t,t.exports,_),t.exports}_.m=O,_.c=x,_.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e;return _.d(r,{a:r}),r},r=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,_.t=function(t,a){if(1&a&&(t=this(t)),8&a)return t;if("object"==typeof t&&t){if(4&a&&t.__esModule)return t;if(16&a&&"function"==typeof t.then)return t}var n=Object.create(null);_.r(n);var o={};e=e||[null,r({}),r([]),r(r)];for(var i=2&a&&t;("object"==typeof i||"function"==typeof i)&&!~e.indexOf(i);i=r(i))Object.getOwnPropertyNames(i).forEach(e=>o[e]=()=>t[e]);return o.default=()=>t,_.d(n,o),n},_.d=(e,r)=>{for(var t in r)_.o(r,t)&&!_.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},_.f={},_.e=e=>Promise.all(Object.keys(_.f).reduce((r,t)=>(_.f[t](e,r),r),[])),_.u=e=>e+"."+{122:"3c2c200586e65203b674",220:"d384edfd5bbcfda33a2a",262:"3fc4ad88e6f8c273d4ad",353:"2c285601a208c3735929",363:"6fc8d18eedbf137940f2",364:"c2fb82c6f484097228c6",439:"3cb9ac7022c8a6074647",481:"96b91d018df31d54d173",553:"b7906877d98a62265533",635:"8c395c854aa2b140b668",713:"103cb5ae248be385b08a",742:"b204789055ded4e07883",747:"b8e9485ebcbb3066eb4b",821:"b58f29814f5900f1f6f8",845:"cc2bc80fbfea6d20a396",888:"09382cc93a2ad3932b31",968:"980219bfdaa6b20f56cb",973:"016a586759b281b79f91"}[e]+".js?v="+{122:"3c2c200586e65203b674",220:"d384edfd5bbcfda33a2a",262:"3fc4ad88e6f8c273d4ad",353:"2c285601a208c3735929",363:"6fc8d18eedbf137940f2",364:"c2fb82c6f484097228c6",439:"3cb9ac7022c8a6074647",481:"96b91d018df31d54d173",553:"b7906877d98a62265533",635:"8c395c854aa2b140b668",713:"103cb5ae248be385b08a",742:"b204789055ded4e07883",747:"b8e9485ebcbb3066eb4b",821:"b58f29814f5900f1f6f8",845:"cc2bc80fbfea6d20a396",888:"09382cc93a2ad3932b31",968:"980219bfdaa6b20f56cb",973:"016a586759b281b79f91"}[e],_.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),_.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),t={},a="sage-agent-internal:",_.l=(e,r,n,o)=>{if(t[e])t[e].push(r);else{var i,f;if(void 0!==n)for(var d=document.getElementsByTagName("script"),l=0;l<d.length;l++){var u=d[l];if(u.getAttribute("src")==e||u.getAttribute("data-webpack")==a+n){i=u;break}}i||(f=!0,(i=document.createElement("script")).charset="utf-8",i.timeout=120,_.nc&&i.setAttribute("nonce",_.nc),i.setAttribute("data-webpack",a+n),i.src=e),t[e]=[r];var c=(r,a)=>{i.onerror=i.onload=null,clearTimeout(s);var n=t[e];if(delete t[e],i.parentNode&&i.parentNode.removeChild(i),n&&n.forEach(e=>e(a)),r)return r(a)},s=setTimeout(c.bind(null,void 0,{type:"timeout",target:i}),12e4);i.onerror=c.bind(null,i.onerror),i.onload=c.bind(null,i.onload),f&&document.head.appendChild(i)}},_.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},(()=>{_.S={};var e={},r={};_.I=(t,a)=>{a||(a=[]);var n=r[t];if(n||(n=r[t]={}),!(a.indexOf(n)>=0)){if(a.push(n),e[t])return e[t];_.o(_.S,t)||(_.S[t]={});var o=_.S[t],i="sage-agent-internal",f=(e,r,t,a)=>{var n=o[e]=o[e]||{},f=n[r];(!f||!f.loaded&&(!a!=!f.eager?a:i>f.from))&&(n[r]={get:t,from:i,eager:!!a})},d=[];return"default"===t&&(f("@anthropic-ai/sdk","0.54.0",()=>_.e(742).then(()=>()=>_(2742))),f("best-effort-json-parser","1.2.1",()=>_.e(439).then(()=>()=>_(7820))),f("codemirror-merge-alpinex","6.10.4",()=>Promise.all([_.e(353),_.e(635),_.e(760),_.e(839)]).then(()=>()=>_(7635))),f("codemirror","6.0.2",()=>Promise.all([_.e(353),_.e(821),_.e(747),_.e(760)]).then(()=>()=>_(8821))),f("diff2html","3.4.52",()=>Promise.all([_.e(122),_.e(379)]).then(()=>()=>_(2122))),f("diff","7.0.0",()=>_.e(713).then(()=>()=>_(5713))),f("diff","0",()=>_.e(481).then(()=>()=>_(7481))),f("marked","15.0.12",()=>_.e(364).then(()=>()=>_(4364))),f("partial-json","0.1.7",()=>_.e(220).then(()=>()=>_(9220))),f("react-bootstrap","2.10.10",()=>Promise.all([_.e(553),_.e(345),_.e(628)]).then(()=>()=>_(4553))),f("rxjs","7.8.2",()=>_.e(888).then(()=>()=>_(2888))),f("sage-agent-internal","0.2.6",()=>Promise.all([_.e(353),_.e(747),_.e(122),_.e(973),_.e(760),_.e(345),_.e(379),_.e(839),_.e(968)]).then(()=>()=>_(9040))),f("uuid","11.1.0",()=>_.e(262).then(()=>()=>_(8262)))),e[t]=d.length?Promise.all(d).then(()=>e[t]=1):1}}})(),(()=>{var e;_.g.importScripts&&(e=_.g.location+"");var r=_.g.document;if(!e&&r&&(r.currentScript&&"SCRIPT"===r.currentScript.tagName.toUpperCase()&&(e=r.currentScript.src),!e)){var t=r.getElementsByTagName("script");if(t.length)for(var a=t.length-1;a>-1&&(!e||!/^http(s?):/.test(e));)e=t[a--].src}if(!e)throw new Error("Automatic publicPath is not supported in this browser");e=e.replace(/^blob:/,"").replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),_.p=e})(),n=e=>{var r=e=>e.split(".").map(e=>+e==e?+e:e),t=/^([^-+]+)?(?:-([^+]+))?(?:\+(.+))?$/.exec(e),a=t[1]?r(t[1]):[];return t[2]&&(a.length++,a.push.apply(a,r(t[2]))),t[3]&&(a.push([]),a.push.apply(a,r(t[3]))),a},o=(e,r)=>{e=n(e),r=n(r);for(var t=0;;){if(t>=e.length)return t<r.length&&"u"!=(typeof r[t])[0];var a=e[t],o=(typeof a)[0];if(t>=r.length)return"u"==o;var i=r[t],f=(typeof i)[0];if(o!=f)return"o"==o&&"n"==f||"s"==f||"u"==o;if("o"!=o&&"u"!=o&&a!=i)return a<i;t++}},i=e=>{var r=e[0],t="";if(1===e.length)return"*";if(r+.5){t+=0==r?">=":-1==r?"<":1==r?"^":2==r?"~":r>0?"=":"!=";for(var a=1,n=1;n<e.length;n++)a--,t+="u"==(typeof(f=e[n]))[0]?"-":(a>0?".":"")+(a=2,f);return t}var o=[];for(n=1;n<e.length;n++){var f=e[n];o.push(0===f?"not("+d()+")":1===f?"("+d()+" || "+d()+")":2===f?o.pop()+" "+o.pop():i(f))}return d();function d(){return o.pop().replace(/^\((.+)\)$/,"$1")}},f=(e,r)=>{if(0 in e){r=n(r);var t=e[0],a=t<0;a&&(t=-t-1);for(var o=0,i=1,d=!0;;i++,o++){var l,u,c=i<e.length?(typeof e[i])[0]:"";if(o>=r.length||"o"==(u=(typeof(l=r[o]))[0]))return!d||("u"==c?i>t&&!a:""==c!=a);if("u"==u){if(!d||"u"!=c)return!1}else if(d)if(c==u)if(i<=t){if(l!=e[i])return!1}else{if(a?l>e[i]:l<e[i])return!1;l!=e[i]&&(d=!1)}else if("s"!=c&&"n"!=c){if(a||i<=t)return!1;d=!1,i--}else{if(i<=t||u<c!=a)return!1;d=!1}else"s"!=c&&"n"!=c&&(d=!1,i--)}}var s=[],p=s.pop.bind(s);for(o=1;o<e.length;o++){var h=e[o];s.push(1==h?p()|p():2==h?p()&p():h?f(h,r):!p())}return!!p()},d=(e,r)=>e&&_.o(e,r),l=e=>(e.loaded=1,e.get()),u=e=>Object.keys(e).reduce((r,t)=>(e[t].eager&&(r[t]=e[t]),r),{}),c=(e,r,t,a)=>{var n=a?u(e[r]):e[r];return(r=Object.keys(n).reduce((e,r)=>!f(t,r)||e&&!o(e,r)?e:r,0))&&n[r]},s=(e,r,t)=>{var a=t?u(e[r]):e[r];return Object.keys(a).reduce((e,r)=>!e||!a[e].loaded&&o(e,r)?r:e,0)},p=(e,r,t,a)=>"Unsatisfied version "+t+" from "+(t&&e[r][t].from)+" of shared singleton module "+r+" (required "+i(a)+")",h=(e,r,t,a,n)=>{var o=e[t];return"No satisfying version ("+i(a)+")"+(n?" for eager consumption":"")+" of shared module "+t+" found in shared scope "+r+".\nAvailable versions: "+Object.keys(o).map(e=>e+" from "+o[e].from).join(", ")},b=e=>{throw new Error(e)},m=e=>{"undefined"!=typeof console&&console.warn&&console.warn(e)},v=(e,r,t)=>t?t():((e,r)=>b("Shared module "+r+" doesn't exist in shared scope "+e))(e,r),y=(g=e=>function(r,t,a,n,o){var i=_.I(r);return i&&i.then&&!a?i.then(e.bind(e,r,_.S[r],t,!1,n,o)):e(r,_.S[r],t,a,n,o)})((e,r,t,a,n,o)=>{if(!d(r,t))return v(e,t,o);var i=c(r,t,n,a);return i?l(i):o?o():void b(h(r,e,t,n,a))}),j=g((e,r,t,a,n,o)=>{if(!d(r,t))return v(e,t,o);var i=s(r,t,a);return f(n,i)||m(p(r,t,i,n)),l(r[t][i])}),w={},P={195:()=>j("default","@codemirror/state",!1,[1,6,2,0]),2084:()=>j("default","@codemirror/language",!1,[1,6,0,0]),3708:()=>j("default","@lezer/common",!1,[1,1,0,0]),5024:()=>j("default","@codemirror/view",!1,[1,6,9,6]),3345:()=>j("default","react",!1,[1,18,2,0]),3379:()=>y("default","diff",!1,[1,7,0,0],()=>_.e(713).then(()=>()=>_(5713))),1839:()=>j("default","@lezer/highlight",!1,[1,1,0,0]),113:()=>y("default","diff",!1,[1,8,0,1],()=>_.e(481).then(()=>()=>_(7481))),135:()=>y("default","@anthropic-ai/sdk",!1,[2,0,54,0],()=>_.e(742).then(()=>()=>_(2742))),389:()=>j("default","@jupyterlab/statedb",!1,[1,4,4,6]),1336:()=>y("default","diff2html",!1,[1,3,4,51],()=>()=>_(2122)),2311:()=>y("default","react-bootstrap",!1,[1,2,10,10],()=>Promise.all([_.e(553),_.e(628)]).then(()=>()=>_(4553))),3139:()=>y("default","codemirror-merge-alpinex",!1,[1,6,10,4],()=>_.e(635).then(()=>()=>_(7635))),3427:()=>j("default","@jupyterlab/docmanager",!1,[1,4,4,6]),3550:()=>y("default","marked",!1,[1,15,0,11],()=>_.e(364).then(()=>()=>_(4364))),4602:()=>j("default","@lumino/signaling",!1,[1,2,0,0]),4744:()=>y("default","uuid",!1,[1,11,1,0],()=>_.e(262).then(()=>()=>_(8262))),5256:()=>j("default","@lumino/widgets",!1,[1,2,3,1,,"alpha",0]),5280:()=>j("default","@jupyterlab/extensionmanager",!1,[1,4,4,6]),6750:()=>y("default","rxjs",!1,[1,7,8,2],()=>_.e(888).then(()=>()=>_(2888))),7332:()=>y("default","codemirror",!1,[1,6,0,2],()=>_.e(821).then(()=>()=>_(8821))),7570:()=>y("default","partial-json",!1,[2,0,1,7],()=>_.e(220).then(()=>()=>_(9220))),8118:()=>j("default","@jupyterlab/codemirror",!1,[1,4,4,6]),8276:()=>y("default","best-effort-json-parser",!1,[1,1,1,3],()=>_.e(439).then(()=>()=>_(7820))),8361:()=>j("default","@jupyterlab/settingregistry",!1,[1,4,4,6]),8531:()=>j("default","@jupyterlab/notebook",!1,[1,4,4,6]),9159:()=>j("default","@jupyterlab/ui-components",!1,[1,4,4,6]),9715:()=>j("default","@jupyterlab/apputils",!1,[1,4,5,6]),7628:()=>j("default","react-dom",!1,[1,18,2,0])},k={345:[3345],379:[3379],628:[7628],760:[195,2084,3708,5024],839:[1839],968:[113,135,389,1336,2311,3139,3427,3550,4602,4744,5256,5280,6750,7332,7570,8118,8276,8361,8531,9159,9715]},S={},_.f.consumes=(e,r)=>{_.o(k,e)&&k[e].forEach(e=>{if(_.o(w,e))return r.push(w[e]);if(!S[e]){var t=r=>{w[e]=0,_.m[e]=t=>{delete _.c[e],t.exports=r()}};S[e]=!0;var a=r=>{delete w[e],_.m[e]=t=>{throw delete _.c[e],r}};try{var n=P[e]();n.then?r.push(w[e]=n.then(t).catch(a)):t(n)}catch(e){a(e)}}})},(()=>{_.b=document.baseURI||self.location.href;var e={431:0};_.f.j=(r,t)=>{var a=_.o(e,r)?e[r]:void 0;if(0!==a)if(a)t.push(a[2]);else if(/^(345|379|628|760|839)$/.test(r))e[r]=0;else{var n=new Promise((t,n)=>a=e[r]=[t,n]);t.push(a[2]=n);var o=_.p+_.u(r),i=new Error;_.l(o,t=>{if(_.o(e,r)&&(0!==(a=e[r])&&(e[r]=void 0),a)){var n=t&&("load"===t.type?"missing":t.type),o=t&&t.target&&t.target.src;i.message="Loading chunk "+r+" failed.\n("+n+": "+o+")",i.name="ChunkLoadError",i.type=n,i.request=o,a[1](i)}},"chunk-"+r,r)}};var r=(r,t)=>{var a,n,[o,i,f]=t,d=0;if(o.some(r=>0!==e[r])){for(a in i)_.o(i,a)&&(_.m[a]=i[a]);f&&f(_)}for(r&&r(t);d<o.length;d++)n=o[d],_.o(e,n)&&e[n]&&e[n][0](),e[n]=0},t=self.webpackChunksage_agent_internal=self.webpackChunksage_agent_internal||[];t.forEach(r.bind(null,0)),t.push=r.bind(null,t.push.bind(t))})(),_.nc=void 0;var E=_(484);(_JUPYTERLAB=void 0===_JUPYTERLAB?{}:_JUPYTERLAB)["sage-agent-internal"]=E})();
1
+ var _JUPYTERLAB;(()=>{"use strict";var e,r,t,a,n,o,i,f,d,l,u,c,s,p,h,b,m,g,v,y,j,w,P,k,S,O={484:(e,r,t)=>{var a={"./index":()=>Promise.all([t.e(353),t.e(747),t.e(122),t.e(973),t.e(760),t.e(345),t.e(379),t.e(839),t.e(968)]).then(()=>()=>t(9040)),"./extension":()=>Promise.all([t.e(353),t.e(747),t.e(122),t.e(973),t.e(760),t.e(345),t.e(379),t.e(839),t.e(968)]).then(()=>()=>t(9040)),"./style":()=>t.e(363).then(()=>()=>t(8363))},n=(e,r)=>(t.R=r,r=t.o(a,e)?a[e]():Promise.resolve().then(()=>{throw new Error('Module "'+e+'" does not exist in container.')}),t.R=void 0,r),o=(e,r)=>{if(t.S){var a="default",n=t.S[a];if(n&&n!==e)throw new Error("Container initialization failed as it has already been initialized with a different share scope");return t.S[a]=e,t.I(a,r)}};t.d(r,{get:()=>n,init:()=>o})}},x={};function _(e){var r=x[e];if(void 0!==r)return r.exports;var t=x[e]={id:e,exports:{}};return O[e].call(t.exports,t,t.exports,_),t.exports}_.m=O,_.c=x,_.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e;return _.d(r,{a:r}),r},r=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,_.t=function(t,a){if(1&a&&(t=this(t)),8&a)return t;if("object"==typeof t&&t){if(4&a&&t.__esModule)return t;if(16&a&&"function"==typeof t.then)return t}var n=Object.create(null);_.r(n);var o={};e=e||[null,r({}),r([]),r(r)];for(var i=2&a&&t;("object"==typeof i||"function"==typeof i)&&!~e.indexOf(i);i=r(i))Object.getOwnPropertyNames(i).forEach(e=>o[e]=()=>t[e]);return o.default=()=>t,_.d(n,o),n},_.d=(e,r)=>{for(var t in r)_.o(r,t)&&!_.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},_.f={},_.e=e=>Promise.all(Object.keys(_.f).reduce((r,t)=>(_.f[t](e,r),r),[])),_.u=e=>e+"."+{122:"3c2c200586e65203b674",220:"d384edfd5bbcfda33a2a",262:"3fc4ad88e6f8c273d4ad",353:"2c285601a208c3735929",363:"6fc8d18eedbf137940f2",364:"c2fb82c6f484097228c6",439:"3cb9ac7022c8a6074647",481:"96b91d018df31d54d173",553:"b7906877d98a62265533",635:"8c395c854aa2b140b668",713:"103cb5ae248be385b08a",742:"b204789055ded4e07883",747:"b8e9485ebcbb3066eb4b",821:"b58f29814f5900f1f6f8",845:"cc2bc80fbfea6d20a396",888:"09382cc93a2ad3932b31",968:"980219bfdaa6b20f56cb",973:"016a586759b281b79f91"}[e]+".js?v="+{122:"3c2c200586e65203b674",220:"d384edfd5bbcfda33a2a",262:"3fc4ad88e6f8c273d4ad",353:"2c285601a208c3735929",363:"6fc8d18eedbf137940f2",364:"c2fb82c6f484097228c6",439:"3cb9ac7022c8a6074647",481:"96b91d018df31d54d173",553:"b7906877d98a62265533",635:"8c395c854aa2b140b668",713:"103cb5ae248be385b08a",742:"b204789055ded4e07883",747:"b8e9485ebcbb3066eb4b",821:"b58f29814f5900f1f6f8",845:"cc2bc80fbfea6d20a396",888:"09382cc93a2ad3932b31",968:"980219bfdaa6b20f56cb",973:"016a586759b281b79f91"}[e],_.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),_.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),t={},a="sage-agent-internal:",_.l=(e,r,n,o)=>{if(t[e])t[e].push(r);else{var i,f;if(void 0!==n)for(var d=document.getElementsByTagName("script"),l=0;l<d.length;l++){var u=d[l];if(u.getAttribute("src")==e||u.getAttribute("data-webpack")==a+n){i=u;break}}i||(f=!0,(i=document.createElement("script")).charset="utf-8",i.timeout=120,_.nc&&i.setAttribute("nonce",_.nc),i.setAttribute("data-webpack",a+n),i.src=e),t[e]=[r];var c=(r,a)=>{i.onerror=i.onload=null,clearTimeout(s);var n=t[e];if(delete t[e],i.parentNode&&i.parentNode.removeChild(i),n&&n.forEach(e=>e(a)),r)return r(a)},s=setTimeout(c.bind(null,void 0,{type:"timeout",target:i}),12e4);i.onerror=c.bind(null,i.onerror),i.onload=c.bind(null,i.onload),f&&document.head.appendChild(i)}},_.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},(()=>{_.S={};var e={},r={};_.I=(t,a)=>{a||(a=[]);var n=r[t];if(n||(n=r[t]={}),!(a.indexOf(n)>=0)){if(a.push(n),e[t])return e[t];_.o(_.S,t)||(_.S[t]={});var o=_.S[t],i="sage-agent-internal",f=(e,r,t,a)=>{var n=o[e]=o[e]||{},f=n[r];(!f||!f.loaded&&(!a!=!f.eager?a:i>f.from))&&(n[r]={get:t,from:i,eager:!!a})},d=[];return"default"===t&&(f("@anthropic-ai/sdk","0.54.0",()=>_.e(742).then(()=>()=>_(2742))),f("best-effort-json-parser","1.2.1",()=>_.e(439).then(()=>()=>_(7820))),f("codemirror-merge-alpinex","6.10.4",()=>Promise.all([_.e(353),_.e(635),_.e(760),_.e(839)]).then(()=>()=>_(7635))),f("codemirror","6.0.2",()=>Promise.all([_.e(353),_.e(821),_.e(747),_.e(760)]).then(()=>()=>_(8821))),f("diff2html","3.4.52",()=>Promise.all([_.e(122),_.e(379)]).then(()=>()=>_(2122))),f("diff","7.0.0",()=>_.e(713).then(()=>()=>_(5713))),f("diff","0",()=>_.e(481).then(()=>()=>_(7481))),f("marked","15.0.12",()=>_.e(364).then(()=>()=>_(4364))),f("partial-json","0.1.7",()=>_.e(220).then(()=>()=>_(9220))),f("react-bootstrap","2.10.10",()=>Promise.all([_.e(553),_.e(345),_.e(628)]).then(()=>()=>_(4553))),f("rxjs","7.8.2",()=>_.e(888).then(()=>()=>_(2888))),f("sage-agent-internal","0.2.8",()=>Promise.all([_.e(353),_.e(747),_.e(122),_.e(973),_.e(760),_.e(345),_.e(379),_.e(839),_.e(968)]).then(()=>()=>_(9040))),f("uuid","11.1.0",()=>_.e(262).then(()=>()=>_(8262)))),e[t]=d.length?Promise.all(d).then(()=>e[t]=1):1}}})(),(()=>{var e;_.g.importScripts&&(e=_.g.location+"");var r=_.g.document;if(!e&&r&&(r.currentScript&&"SCRIPT"===r.currentScript.tagName.toUpperCase()&&(e=r.currentScript.src),!e)){var t=r.getElementsByTagName("script");if(t.length)for(var a=t.length-1;a>-1&&(!e||!/^http(s?):/.test(e));)e=t[a--].src}if(!e)throw new Error("Automatic publicPath is not supported in this browser");e=e.replace(/^blob:/,"").replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),_.p=e})(),n=e=>{var r=e=>e.split(".").map(e=>+e==e?+e:e),t=/^([^-+]+)?(?:-([^+]+))?(?:\+(.+))?$/.exec(e),a=t[1]?r(t[1]):[];return t[2]&&(a.length++,a.push.apply(a,r(t[2]))),t[3]&&(a.push([]),a.push.apply(a,r(t[3]))),a},o=(e,r)=>{e=n(e),r=n(r);for(var t=0;;){if(t>=e.length)return t<r.length&&"u"!=(typeof r[t])[0];var a=e[t],o=(typeof a)[0];if(t>=r.length)return"u"==o;var i=r[t],f=(typeof i)[0];if(o!=f)return"o"==o&&"n"==f||"s"==f||"u"==o;if("o"!=o&&"u"!=o&&a!=i)return a<i;t++}},i=e=>{var r=e[0],t="";if(1===e.length)return"*";if(r+.5){t+=0==r?">=":-1==r?"<":1==r?"^":2==r?"~":r>0?"=":"!=";for(var a=1,n=1;n<e.length;n++)a--,t+="u"==(typeof(f=e[n]))[0]?"-":(a>0?".":"")+(a=2,f);return t}var o=[];for(n=1;n<e.length;n++){var f=e[n];o.push(0===f?"not("+d()+")":1===f?"("+d()+" || "+d()+")":2===f?o.pop()+" "+o.pop():i(f))}return d();function d(){return o.pop().replace(/^\((.+)\)$/,"$1")}},f=(e,r)=>{if(0 in e){r=n(r);var t=e[0],a=t<0;a&&(t=-t-1);for(var o=0,i=1,d=!0;;i++,o++){var l,u,c=i<e.length?(typeof e[i])[0]:"";if(o>=r.length||"o"==(u=(typeof(l=r[o]))[0]))return!d||("u"==c?i>t&&!a:""==c!=a);if("u"==u){if(!d||"u"!=c)return!1}else if(d)if(c==u)if(i<=t){if(l!=e[i])return!1}else{if(a?l>e[i]:l<e[i])return!1;l!=e[i]&&(d=!1)}else if("s"!=c&&"n"!=c){if(a||i<=t)return!1;d=!1,i--}else{if(i<=t||u<c!=a)return!1;d=!1}else"s"!=c&&"n"!=c&&(d=!1,i--)}}var s=[],p=s.pop.bind(s);for(o=1;o<e.length;o++){var h=e[o];s.push(1==h?p()|p():2==h?p()&p():h?f(h,r):!p())}return!!p()},d=(e,r)=>e&&_.o(e,r),l=e=>(e.loaded=1,e.get()),u=e=>Object.keys(e).reduce((r,t)=>(e[t].eager&&(r[t]=e[t]),r),{}),c=(e,r,t,a)=>{var n=a?u(e[r]):e[r];return(r=Object.keys(n).reduce((e,r)=>!f(t,r)||e&&!o(e,r)?e:r,0))&&n[r]},s=(e,r,t)=>{var a=t?u(e[r]):e[r];return Object.keys(a).reduce((e,r)=>!e||!a[e].loaded&&o(e,r)?r:e,0)},p=(e,r,t,a)=>"Unsatisfied version "+t+" from "+(t&&e[r][t].from)+" of shared singleton module "+r+" (required "+i(a)+")",h=(e,r,t,a,n)=>{var o=e[t];return"No satisfying version ("+i(a)+")"+(n?" for eager consumption":"")+" of shared module "+t+" found in shared scope "+r+".\nAvailable versions: "+Object.keys(o).map(e=>e+" from "+o[e].from).join(", ")},b=e=>{throw new Error(e)},m=e=>{"undefined"!=typeof console&&console.warn&&console.warn(e)},v=(e,r,t)=>t?t():((e,r)=>b("Shared module "+r+" doesn't exist in shared scope "+e))(e,r),y=(g=e=>function(r,t,a,n,o){var i=_.I(r);return i&&i.then&&!a?i.then(e.bind(e,r,_.S[r],t,!1,n,o)):e(r,_.S[r],t,a,n,o)})((e,r,t,a,n,o)=>{if(!d(r,t))return v(e,t,o);var i=c(r,t,n,a);return i?l(i):o?o():void b(h(r,e,t,n,a))}),j=g((e,r,t,a,n,o)=>{if(!d(r,t))return v(e,t,o);var i=s(r,t,a);return f(n,i)||m(p(r,t,i,n)),l(r[t][i])}),w={},P={195:()=>j("default","@codemirror/state",!1,[1,6,2,0]),2084:()=>j("default","@codemirror/language",!1,[1,6,0,0]),3708:()=>j("default","@lezer/common",!1,[1,1,0,0]),5024:()=>j("default","@codemirror/view",!1,[1,6,9,6]),3345:()=>j("default","react",!1,[1,18,2,0]),3379:()=>y("default","diff",!1,[1,7,0,0],()=>_.e(713).then(()=>()=>_(5713))),1839:()=>j("default","@lezer/highlight",!1,[1,1,0,0]),113:()=>y("default","diff",!1,[1,8,0,1],()=>_.e(481).then(()=>()=>_(7481))),135:()=>y("default","@anthropic-ai/sdk",!1,[2,0,54,0],()=>_.e(742).then(()=>()=>_(2742))),389:()=>j("default","@jupyterlab/statedb",!1,[1,4,4,6]),1336:()=>y("default","diff2html",!1,[1,3,4,51],()=>()=>_(2122)),2311:()=>y("default","react-bootstrap",!1,[1,2,10,10],()=>Promise.all([_.e(553),_.e(628)]).then(()=>()=>_(4553))),3139:()=>y("default","codemirror-merge-alpinex",!1,[1,6,10,4],()=>_.e(635).then(()=>()=>_(7635))),3427:()=>j("default","@jupyterlab/docmanager",!1,[1,4,4,6]),3550:()=>y("default","marked",!1,[1,15,0,11],()=>_.e(364).then(()=>()=>_(4364))),4602:()=>j("default","@lumino/signaling",!1,[1,2,0,0]),4744:()=>y("default","uuid",!1,[1,11,1,0],()=>_.e(262).then(()=>()=>_(8262))),5256:()=>j("default","@lumino/widgets",!1,[1,2,3,1,,"alpha",0]),5280:()=>j("default","@jupyterlab/extensionmanager",!1,[1,4,4,6]),6750:()=>y("default","rxjs",!1,[1,7,8,2],()=>_.e(888).then(()=>()=>_(2888))),7332:()=>y("default","codemirror",!1,[1,6,0,2],()=>_.e(821).then(()=>()=>_(8821))),7570:()=>y("default","partial-json",!1,[2,0,1,7],()=>_.e(220).then(()=>()=>_(9220))),8118:()=>j("default","@jupyterlab/codemirror",!1,[1,4,4,6]),8276:()=>y("default","best-effort-json-parser",!1,[1,1,1,3],()=>_.e(439).then(()=>()=>_(7820))),8361:()=>j("default","@jupyterlab/settingregistry",!1,[1,4,4,6]),8531:()=>j("default","@jupyterlab/notebook",!1,[1,4,4,6]),9159:()=>j("default","@jupyterlab/ui-components",!1,[1,4,4,6]),9715:()=>j("default","@jupyterlab/apputils",!1,[1,4,5,6]),7628:()=>j("default","react-dom",!1,[1,18,2,0])},k={345:[3345],379:[3379],628:[7628],760:[195,2084,3708,5024],839:[1839],968:[113,135,389,1336,2311,3139,3427,3550,4602,4744,5256,5280,6750,7332,7570,8118,8276,8361,8531,9159,9715]},S={},_.f.consumes=(e,r)=>{_.o(k,e)&&k[e].forEach(e=>{if(_.o(w,e))return r.push(w[e]);if(!S[e]){var t=r=>{w[e]=0,_.m[e]=t=>{delete _.c[e],t.exports=r()}};S[e]=!0;var a=r=>{delete w[e],_.m[e]=t=>{throw delete _.c[e],r}};try{var n=P[e]();n.then?r.push(w[e]=n.then(t).catch(a)):t(n)}catch(e){a(e)}}})},(()=>{_.b=document.baseURI||self.location.href;var e={431:0};_.f.j=(r,t)=>{var a=_.o(e,r)?e[r]:void 0;if(0!==a)if(a)t.push(a[2]);else if(/^(345|379|628|760|839)$/.test(r))e[r]=0;else{var n=new Promise((t,n)=>a=e[r]=[t,n]);t.push(a[2]=n);var o=_.p+_.u(r),i=new Error;_.l(o,t=>{if(_.o(e,r)&&(0!==(a=e[r])&&(e[r]=void 0),a)){var n=t&&("load"===t.type?"missing":t.type),o=t&&t.target&&t.target.src;i.message="Loading chunk "+r+" failed.\n("+n+": "+o+")",i.name="ChunkLoadError",i.type=n,i.request=o,a[1](i)}},"chunk-"+r,r)}};var r=(r,t)=>{var a,n,[o,i,f]=t,d=0;if(o.some(r=>0!==e[r])){for(a in i)_.o(i,a)&&(_.m[a]=i[a]);f&&f(_)}for(r&&r(t);d<o.length;d++)n=o[d],_.o(e,n)&&e[n]&&e[n][0](),e[n]=0},t=self.webpackChunksage_agent_internal=self.webpackChunksage_agent_internal||[];t.forEach(r.bind(null,0)),t.push=r.bind(null,t.push.bind(t))})(),_.nc=void 0;var E=_(484);(_JUPYTERLAB=void 0===_JUPYTERLAB?{}:_JUPYTERLAB)["sage-agent-internal"]=E})();
@@ -12,6 +12,9 @@ module.exports = {
12
12
  headless: true,
13
13
  viewport: { width: 1920, height: 1080 }
14
14
  },
15
+ video: {
16
+ size: { width: 1920, height: 1080 }
17
+ },
15
18
  // Add multiple reporters for better CI integration
16
19
  reporter: [
17
20
  ['html'], // Keep the existing HTML reporter
@@ -0,0 +1,44 @@
1
+ # Slack Test Notification
2
+
3
+ This script (`test_slack.py`) is used to post UI test results to Slack channels as part of the GitHub Actions workflow.
4
+
5
+ ## How it works
6
+
7
+ 1. **Triggered by GitHub Actions**: The script runs at the end of the `run-tests.yml` workflow
8
+ 2. **Reads test results**: It reads the `test-summary.md` file generated by the test suite
9
+ 3. **Posts to Slack**: It posts the test results along with PR information to all accessible Slack channels
10
+
11
+ ## Configuration
12
+
13
+ The script requires the following environment variables to be set in GitHub repository secrets:
14
+
15
+ - `SLACK_BOT_TOKEN`: The Slack bot token for authentication
16
+
17
+ The following environment variables are automatically set by GitHub Actions:
18
+ - `GITHUB_PR_NUMBER`: Pull request number
19
+ - `GITHUB_PR_URL`: Pull request URL
20
+ - `GITHUB_REPOSITORY`: Repository name
21
+
22
+ ## Slack Bot Setup
23
+
24
+ To use this script, you need to:
25
+
26
+ 1. Create a Slack app and bot in your workspace
27
+ 2. Add the bot to the channels where you want notifications
28
+ 3. Set the `SLACK_BOT_TOKEN` secret in your GitHub repository settings
29
+
30
+ ## Message Format
31
+
32
+ The script posts a formatted message containing:
33
+ - PR number and link
34
+ - Repository name
35
+ - Complete test results summary (same content as GitHub comment)
36
+ - Test statistics (passed/failed/skipped)
37
+ - Links to artifacts and workflow run
38
+
39
+ ## Dependencies
40
+
41
+ - `slack-sdk`: For Slack API communication
42
+ - `python-dotenv`: For environment variable handling
43
+
44
+ Both are automatically installed by the GitHub Actions workflow.
@@ -0,0 +1,245 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Slack bot for posting UI test results to Slack channels.
4
+ This script posts test results and PR links to Slack.
5
+ """
6
+
7
+ import os
8
+ import sys
9
+ import time
10
+ import requests
11
+ from slack_sdk import WebClient
12
+ from slack_sdk.errors import SlackApiError
13
+ def get_pr_info():
14
+ """Get PR information from environment variables set by GitHub Actions."""
15
+ pr_number = os.environ.get("GITHUB_PR_NUMBER", "")
16
+ pr_url = os.environ.get("GITHUB_PR_URL", "")
17
+ repo_name = os.environ.get("GITHUB_REPOSITORY", "")
18
+ return pr_number, pr_url, repo_name
19
+
20
+ def get_test_results_content():
21
+ """Read the test summary content that would be posted to GitHub."""
22
+ summary_path = "./test-summary.md"
23
+
24
+ try:
25
+ if os.path.exists(summary_path):
26
+ with open(summary_path, 'r', encoding='utf-8') as f:
27
+ return f.read()
28
+ else:
29
+ return "❌ **Test Summary Not Available**\n\nTest summary file was not generated."
30
+ except Exception as e:
31
+ print(f"Error reading test summary: {e}")
32
+ return f"❌ **Error Reading Test Summary**\n\nFailed to read test summary file: {str(e)}"
33
+
34
+ def format_slack_message(pr_number, pr_url, repo_name, test_content):
35
+ """Format the message for Slack with PR info and test results."""
36
+ if pr_number and pr_url:
37
+ header = f"🔄 *UI Test Results for PR #{pr_number}*\n"
38
+ header += f"📋 *Repository:* {repo_name}\n"
39
+ header += f"🔗 *PR Link:* <{pr_url}|View Pull Request>\n\n"
40
+ else:
41
+ header = f"🔄 *UI Test Results*\n"
42
+ header += f"📋 *Repository:* {repo_name}\n\n"
43
+
44
+ # Convert markdown to Slack-friendly format
45
+ slack_content = test_content
46
+ # Convert markdown headers to bold text
47
+ slack_content = slack_content.replace("## ", "*").replace("#", "*")
48
+ # Convert markdown bold to Slack bold
49
+ slack_content = slack_content.replace("**", "*")
50
+ # Convert markdown links to Slack format where possible
51
+ # Note: This is a basic conversion, more complex regex might be needed
52
+
53
+ message = header + slack_content
54
+
55
+ # Slack has a 4000 character limit for messages
56
+ max_length = 3900 # Leave some buffer
57
+ if len(message) > max_length:
58
+ message = message[:max_length] + "\n\n⚠️ *Message truncated due to length limit.*"
59
+
60
+ return message
61
+
62
+ def get_accessible_channels(client):
63
+ """Get channels where the bot can actually post messages."""
64
+ print("🔍 Finding accessible channels...")
65
+ accessible_channels = []
66
+
67
+ try:
68
+ # Get all public channels where the bot is a member
69
+ response = client.conversations_list(types="public_channel", limit=1000)
70
+ all_channels = response.get("channels", [])
71
+
72
+ print(f"Found {len(all_channels)} public channels. Testing access...")
73
+
74
+ for channel in all_channels:
75
+ channel_id = channel["id"]
76
+ channel_name = channel["name"]
77
+
78
+ # Check if bot is a member
79
+ try:
80
+ info_response = client.conversations_info(channel=channel_id)
81
+ channel_info = info_response["channel"]
82
+ is_member = channel_info.get("is_member", False)
83
+
84
+ if is_member:
85
+ print(f" ✅ Bot is member of #{channel_name}")
86
+ accessible_channels.append(channel)
87
+
88
+ except SlackApiError as e:
89
+ if e.response["error"] != "channel_not_found":
90
+ print(f" ❌ Error accessing #{channel_name}: {e.response['error']}")
91
+
92
+ except SlackApiError as e:
93
+ print(f"❌ Error getting public channels: {e.response['error']}")
94
+
95
+ print(f"Found {len(accessible_channels)} accessible channels")
96
+ return accessible_channels
97
+
98
+ def upload_video_file(client, channel_id, video_path):
99
+ """Upload video file to Slack channel using the new upload API."""
100
+ try:
101
+ if os.path.exists(video_path):
102
+ print(f"📹 Uploading video: {os.path.basename(video_path)}")
103
+
104
+ # Get file size
105
+ file_size = os.path.getsize(video_path)
106
+ filename = os.path.basename(video_path)
107
+
108
+ # Step 1: Get upload URL
109
+ upload_response = client.files_getUploadURLExternal(
110
+ filename=filename,
111
+ length=file_size
112
+ )
113
+
114
+ upload_url = upload_response["upload_url"]
115
+ file_id = upload_response["file_id"]
116
+
117
+ # Step 2: Upload file to the URL
118
+ import requests
119
+ with open(video_path, 'rb') as file_data:
120
+ upload_result = requests.post(upload_url, files={"file": file_data})
121
+
122
+ if upload_result.status_code != 200:
123
+ print(f"❌ Error uploading file data: HTTP {upload_result.status_code}")
124
+ return False
125
+
126
+ # Step 3: Complete the upload
127
+ complete_response = client.files_completeUploadExternal(
128
+ files=[{
129
+ "id": file_id,
130
+ "title": "SP500 Test Final Video"
131
+ }],
132
+ channel_id=channel_id,
133
+ initial_comment="📹 UI Test Video Results"
134
+ )
135
+
136
+ print(f"✅ Video uploaded successfully")
137
+ return True
138
+ else:
139
+ print(f"⚠️ Video file not found: {video_path}")
140
+ return False
141
+ except SlackApiError as e:
142
+ print(f"❌ Error uploading video: {e.response['error']}")
143
+ return False
144
+ except Exception as e:
145
+ print(f"❌ Error uploading video: {str(e)}")
146
+ return False
147
+
148
+ def post_test_results(client, channel_id, channel_name, message, video_path=None):
149
+ """Post test results message to a specific channel with optional video upload."""
150
+ try:
151
+ # First, upload the video if provided and exists
152
+ if video_path and os.path.exists(video_path):
153
+ upload_video_file(client, channel_id, video_path)
154
+ time.sleep(2) # Wait a bit between video upload and message post
155
+
156
+ response = client.chat_postMessage(
157
+ channel=channel_id,
158
+ text=message,
159
+ mrkdwn=True # Enable Slack markdown formatting
160
+ )
161
+ print(f"✅ Test results posted successfully to #{channel_name}")
162
+ return True
163
+ except SlackApiError as e:
164
+ print(f"❌ Error posting to #{channel_name}: {e.response['error']}")
165
+ return False
166
+
167
+ def main():
168
+ """Main function to post test results to Slack channels."""
169
+
170
+ # Check if bot token is set
171
+ bot_token = os.environ.get("SLACK_BOT_TOKEN")
172
+ if not bot_token:
173
+ print("❌ Error: SLACK_BOT_TOKEN environment variable not set!")
174
+ print("This script requires a Slack bot token to function.")
175
+ sys.exit(1)
176
+
177
+ # Initialize the Slack client
178
+ client = WebClient(token=bot_token)
179
+
180
+ # Test the connection
181
+ try:
182
+ auth_response = client.auth_test()
183
+ bot_name = auth_response["user"]
184
+ bot_id = auth_response["user_id"]
185
+ team_name = auth_response.get("team", "Unknown Team")
186
+ print(f"🤖 Connected as bot: {bot_name} (ID: {bot_id}) in team: {team_name}")
187
+
188
+ except SlackApiError as e:
189
+ print(f"❌ Error connecting to Slack: {e.response['error']}")
190
+ sys.exit(1)
191
+
192
+ # Get PR information
193
+ pr_number, pr_url, repo_name = get_pr_info()
194
+ print(f"📋 PR Info - Number: {pr_number}, Repository: {repo_name}")
195
+ if pr_url:
196
+ print(f"🔗 PR URL: {pr_url}")
197
+
198
+ # Get test results content
199
+ print("📖 Reading test results...")
200
+ test_content = get_test_results_content()
201
+
202
+ # Set video file path
203
+ video_path = os.path.join(os.path.dirname(__file__), "screenshots", "sp500_test_final.mp4")
204
+ print(f"📹 Video file path: {video_path}")
205
+
206
+ # Check if video file exists
207
+ if os.path.exists(video_path):
208
+ print(f"✅ Video file found: {os.path.basename(video_path)}")
209
+ else:
210
+ print(f"⚠️ Video file not found at: {video_path}")
211
+ video_path = None
212
+
213
+ # Format message for Slack
214
+ slack_message = format_slack_message(pr_number, pr_url, repo_name, test_content)
215
+
216
+ # Get channels the bot can access
217
+ bot_channels = get_accessible_channels(client)
218
+
219
+ if not bot_channels:
220
+ print("❌ Bot is not a member of any accessible channels!")
221
+ print("Make sure to invite the bot to at least one channel.")
222
+ sys.exit(1)
223
+
224
+ print(f"📢 Found {len(bot_channels)} channels to post to:")
225
+ for channel in bot_channels:
226
+ print(f" - #{channel['name']}")
227
+
228
+ # Post to each accessible channel
229
+ print(f"\n🚀 Posting test results...")
230
+ success_count = 0
231
+
232
+ for channel in bot_channels:
233
+ print(f"\n📤 Posting to #{channel['name']}...")
234
+ if post_test_results(client, channel["id"], channel["name"], slack_message, video_path):
235
+ success_count += 1
236
+ time.sleep(2) # Rate limiting - wait 2 seconds between posts to allow for video upload
237
+
238
+ print(f"\n✅ Completed! Successfully posted to {success_count}/{len(bot_channels)} channels.")
239
+
240
+ if success_count == 0:
241
+ print("⚠️ No messages were posted successfully.")
242
+ sys.exit(1)
243
+
244
+ if __name__ == "__main__":
245
+ main()