@64mb/freelens-power 1.0.3 → 1.2.0

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 (224) hide show
  1. package/README.md +9 -4
  2. package/THIRD_PARTY_LICENSES +1707 -0
  3. package/out/main/ai.js +63 -23
  4. package/out/main/ai.js.map +1 -1
  5. package/out/main/cluster-icons-catalog.js +28 -0
  6. package/out/main/cluster-icons-catalog.js.map +1 -0
  7. package/out/main/cluster-icons.js +125 -0
  8. package/out/main/cluster-icons.js.map +1 -0
  9. package/out/main/common/ai-terminal-context.js +51 -0
  10. package/out/main/common/ai-terminal-context.js.map +1 -0
  11. package/out/main/common/ai.js.map +1 -1
  12. package/out/main/common/cluster-icon-ipc.js +6 -0
  13. package/out/main/common/cluster-icon-ipc.js.map +1 -0
  14. package/out/main/common/cluster-icons.js +121 -0
  15. package/out/main/common/cluster-icons.js.map +1 -0
  16. package/out/main/common/dashboard.js +1 -1
  17. package/out/main/common/dashboard.js.map +1 -1
  18. package/out/main/common/monitoring-history.js +52 -0
  19. package/out/main/common/monitoring-history.js.map +1 -0
  20. package/out/main/common/settings-export.js +3 -1
  21. package/out/main/common/settings-export.js.map +1 -1
  22. package/out/main/common/store/cluster-icons-store.js +32 -0
  23. package/out/main/common/store/cluster-icons-store.js.map +1 -0
  24. package/out/main/common/store/monitoring-preferences-store.js +30 -2
  25. package/out/main/common/store/monitoring-preferences-store.js.map +1 -1
  26. package/out/main/dashboard-views.js +132 -28
  27. package/out/main/dashboard-views.js.map +1 -1
  28. package/out/main/diagnostics-menu-order.js +57 -0
  29. package/out/main/diagnostics-menu-order.js.map +1 -0
  30. package/out/main/index.js +11 -1
  31. package/out/main/index.js.map +1 -1
  32. package/out/main/monitoring-history-database.js +103 -0
  33. package/out/main/monitoring-history-database.js.map +1 -0
  34. package/out/main/monitoring-history-worker.js +61 -0
  35. package/out/main/monitoring-history-worker.js.map +1 -0
  36. package/out/main/monitoring-history.js +110 -0
  37. package/out/main/monitoring-history.js.map +1 -0
  38. package/out/renderer/_virtual/_global-external_mobx.js +2 -1
  39. package/out/renderer/_virtual/_global-external_react-dom.js +2 -1
  40. package/out/renderer/_virtual/_global-external_react.js +10 -5
  41. package/out/renderer/_virtual/_rolldown/runtime.js +22 -0
  42. package/out/renderer/ai-terminal-context.js +200 -0
  43. package/out/renderer/ai-terminal-context.js.map +1 -0
  44. package/out/renderer/ai.js +90 -9
  45. package/out/renderer/ai.js.map +1 -1
  46. package/out/renderer/appearance.js +1 -0
  47. package/out/renderer/appearance.js.map +1 -1
  48. package/out/renderer/cluster-icon-colors.js +188 -0
  49. package/out/renderer/cluster-icon-colors.js.map +1 -0
  50. package/out/renderer/cluster-icons.js +304 -0
  51. package/out/renderer/cluster-icons.js.map +1 -0
  52. package/out/renderer/dashboard.js +8 -5
  53. package/out/renderer/dashboard.js.map +1 -1
  54. package/out/renderer/details/secret-certificate-details.js +9 -2
  55. package/out/renderer/details/secret-certificate-details.js.map +1 -1
  56. package/out/renderer/diagnostics.css.js +39 -0
  57. package/out/renderer/diagnostics.css.js.map +1 -0
  58. package/out/renderer/diagnostics.js +1100 -0
  59. package/out/renderer/diagnostics.js.map +1 -0
  60. package/out/renderer/index.js +32 -0
  61. package/out/renderer/index.js.map +1 -1
  62. package/out/renderer/monitoring-collector.js +202 -0
  63. package/out/renderer/monitoring-collector.js.map +1 -0
  64. package/out/renderer/monitoring-details-chart.js +42 -0
  65. package/out/renderer/monitoring-details-chart.js.map +1 -0
  66. package/out/renderer/monitoring-history-collection.js +168 -0
  67. package/out/renderer/monitoring-history-collection.js.map +1 -0
  68. package/out/renderer/monitoring-history-view.js +227 -0
  69. package/out/renderer/monitoring-history-view.js.map +1 -0
  70. package/out/renderer/monitoring-history.js +19 -0
  71. package/out/renderer/monitoring-history.js.map +1 -0
  72. package/out/renderer/monitoring.js +153 -139
  73. package/out/renderer/monitoring.js.map +1 -1
  74. package/out/renderer/node-monitoring.js +127 -0
  75. package/out/renderer/node-monitoring.js.map +1 -0
  76. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/arrayLikeToArray.js +10 -0
  77. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/arrayLikeToArray.js.map +1 -0
  78. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/arrayWithHoles.js +8 -0
  79. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/arrayWithHoles.js.map +1 -0
  80. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/arrayWithoutHoles.js +9 -0
  81. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/arrayWithoutHoles.js.map +1 -0
  82. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/assertThisInitialized.js +9 -0
  83. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/assertThisInitialized.js.map +1 -0
  84. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/classCallCheck.js +8 -0
  85. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/classCallCheck.js.map +1 -0
  86. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/createClass.js +15 -0
  87. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/createClass.js.map +1 -0
  88. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/createSuper.js +19 -0
  89. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/createSuper.js.map +1 -0
  90. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/defineProperty.js +14 -0
  91. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/defineProperty.js.map +1 -0
  92. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/extends.js +19 -0
  93. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/extends.js.map +1 -0
  94. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/getPrototypeOf.js +15 -0
  95. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/getPrototypeOf.js.map +1 -0
  96. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/inherits.js +14 -0
  97. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/inherits.js.map +1 -0
  98. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/isNativeReflectConstruct.js +18 -0
  99. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/isNativeReflectConstruct.js.map +1 -0
  100. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/iterableToArray.js +8 -0
  101. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/iterableToArray.js.map +1 -0
  102. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/iterableToArrayLimit.js +26 -0
  103. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/iterableToArrayLimit.js.map +1 -0
  104. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/nonIterableRest.js +8 -0
  105. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/nonIterableRest.js.map +1 -0
  106. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/nonIterableSpread.js +8 -0
  107. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/nonIterableSpread.js.map +1 -0
  108. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/objectSpread2.js +27 -0
  109. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/objectSpread2.js.map +1 -0
  110. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/objectWithoutProperties.js +15 -0
  111. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/objectWithoutProperties.js.map +1 -0
  112. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js +14 -0
  113. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js.map +1 -0
  114. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/possibleConstructorReturn.js +12 -0
  115. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/possibleConstructorReturn.js.map +1 -0
  116. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/setPrototypeOf.js +15 -0
  117. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/setPrototypeOf.js.map +1 -0
  118. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/slicedToArray.js +12 -0
  119. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/slicedToArray.js.map +1 -0
  120. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/taggedTemplateLiteral.js +8 -0
  121. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/taggedTemplateLiteral.js.map +1 -0
  122. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/toConsumableArray.js +12 -0
  123. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/toConsumableArray.js.map +1 -0
  124. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/toPrimitive.js +16 -0
  125. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/toPrimitive.js.map +1 -0
  126. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/toPropertyKey.js +11 -0
  127. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/toPropertyKey.js.map +1 -0
  128. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/typeof.js +18 -0
  129. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/typeof.js.map +1 -0
  130. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/unsupportedIterableToArray.js +13 -0
  131. package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/unsupportedIterableToArray.js.map +1 -0
  132. package/out/renderer/node_modules/.pnpm/@emotion_cache@11.14.0/node_modules/@emotion/cache/dist/emotion-cache.browser.esm.js +237 -0
  133. package/out/renderer/node_modules/.pnpm/@emotion_cache@11.14.0/node_modules/@emotion/cache/dist/emotion-cache.browser.esm.js.map +1 -0
  134. package/out/renderer/node_modules/.pnpm/@emotion_hash@0.9.2/node_modules/@emotion/hash/dist/emotion-hash.esm.js +25 -0
  135. package/out/renderer/node_modules/.pnpm/@emotion_hash@0.9.2/node_modules/@emotion/hash/dist/emotion-hash.esm.js.map +1 -0
  136. package/out/renderer/node_modules/.pnpm/@emotion_memoize@0.9.0/node_modules/@emotion/memoize/dist/emotion-memoize.esm.js +12 -0
  137. package/out/renderer/node_modules/.pnpm/@emotion_memoize@0.9.0/node_modules/@emotion/memoize/dist/emotion-memoize.esm.js.map +1 -0
  138. package/out/renderer/node_modules/.pnpm/@emotion_react@11.14.0_@types_react@17.0.93_react@17.0.2/node_modules/@emotion/react/dist/emotion-element-f0de968e.browser.esm.js +58 -0
  139. package/out/renderer/node_modules/.pnpm/@emotion_react@11.14.0_@types_react@17.0.93_react@17.0.2/node_modules/@emotion/react/dist/emotion-element-f0de968e.browser.esm.js.map +1 -0
  140. package/out/renderer/node_modules/.pnpm/@emotion_react@11.14.0_@types_react@17.0.93_react@17.0.2/node_modules/@emotion/react/dist/emotion-react.browser.esm.js +54 -0
  141. package/out/renderer/node_modules/.pnpm/@emotion_react@11.14.0_@types_react@17.0.93_react@17.0.2/node_modules/@emotion/react/dist/emotion-react.browser.esm.js.map +1 -0
  142. package/out/renderer/node_modules/.pnpm/@emotion_serialize@1.3.3/node_modules/@emotion/serialize/dist/emotion-serialize.esm.js +133 -0
  143. package/out/renderer/node_modules/.pnpm/@emotion_serialize@1.3.3/node_modules/@emotion/serialize/dist/emotion-serialize.esm.js.map +1 -0
  144. package/out/renderer/node_modules/.pnpm/@emotion_sheet@1.4.0/node_modules/@emotion/sheet/dist/emotion-sheet.esm.js +65 -0
  145. package/out/renderer/node_modules/.pnpm/@emotion_sheet@1.4.0/node_modules/@emotion/sheet/dist/emotion-sheet.esm.js.map +1 -0
  146. package/out/renderer/node_modules/.pnpm/@emotion_unitless@0.10.0/node_modules/@emotion/unitless/dist/emotion-unitless.esm.js +54 -0
  147. package/out/renderer/node_modules/.pnpm/@emotion_unitless@0.10.0/node_modules/@emotion/unitless/dist/emotion-unitless.esm.js.map +1 -0
  148. package/out/renderer/node_modules/.pnpm/@emotion_use-insertion-effect-with-fallbacks@1.2.0_react@17.0.2/node_modules/@emotion/use-insertion-effect-with-fallbacks/dist/emotion-use-insertion-effect-with-fallbacks.browser.esm.js +12 -0
  149. package/out/renderer/node_modules/.pnpm/@emotion_use-insertion-effect-with-fallbacks@1.2.0_react@17.0.2/node_modules/@emotion/use-insertion-effect-with-fallbacks/dist/emotion-use-insertion-effect-with-fallbacks.browser.esm.js.map +1 -0
  150. package/out/renderer/node_modules/.pnpm/@emotion_utils@1.4.2/node_modules/@emotion/utils/dist/emotion-utils.browser.esm.js +30 -0
  151. package/out/renderer/node_modules/.pnpm/@emotion_utils@1.4.2/node_modules/@emotion/utils/dist/emotion-utils.browser.esm.js.map +1 -0
  152. package/out/renderer/node_modules/.pnpm/@floating-ui_dom@1.7.2/node_modules/@floating-ui/dom/dist/floating-ui.dom.js +211 -0
  153. package/out/renderer/node_modules/.pnpm/@floating-ui_dom@1.7.2/node_modules/@floating-ui/dom/dist/floating-ui.dom.js.map +1 -0
  154. package/out/renderer/node_modules/.pnpm/@floating-ui_utils@0.2.10/node_modules/@floating-ui/utils/dist/floating-ui.utils.dom.js +97 -0
  155. package/out/renderer/node_modules/.pnpm/@floating-ui_utils@0.2.10/node_modules/@floating-ui/utils/dist/floating-ui.utils.dom.js.map +1 -0
  156. package/out/renderer/node_modules/.pnpm/@floating-ui_utils@0.2.10/node_modules/@floating-ui/utils/dist/floating-ui.utils.js +31 -0
  157. package/out/renderer/node_modules/.pnpm/@floating-ui_utils@0.2.10/node_modules/@floating-ui/utils/dist/floating-ui.utils.js.map +1 -0
  158. package/out/renderer/node_modules/.pnpm/hoist-non-react-statics@3.3.2/node_modules/hoist-non-react-statics/dist/hoist-non-react-statics.cjs.js +93 -0
  159. package/out/renderer/node_modules/.pnpm/hoist-non-react-statics@3.3.2/node_modules/hoist-non-react-statics/dist/hoist-non-react-statics.cjs.js.map +1 -0
  160. package/out/renderer/node_modules/.pnpm/memoize-one@6.0.0/node_modules/memoize-one/dist/memoize-one.esm.js +38 -0
  161. package/out/renderer/node_modules/.pnpm/memoize-one@6.0.0/node_modules/memoize-one/dist/memoize-one.esm.js.map +1 -0
  162. package/out/renderer/node_modules/.pnpm/react-is@16.13.1/node_modules/react-is/cjs/react-is.development.js +159 -0
  163. package/out/renderer/node_modules/.pnpm/react-is@16.13.1/node_modules/react-is/cjs/react-is.development.js.map +1 -0
  164. package/out/renderer/node_modules/.pnpm/react-is@16.13.1/node_modules/react-is/cjs/react-is.production.min.js +103 -0
  165. package/out/renderer/node_modules/.pnpm/react-is@16.13.1/node_modules/react-is/cjs/react-is.production.min.js.map +1 -0
  166. package/out/renderer/node_modules/.pnpm/react-is@16.13.1/node_modules/react-is/index.js +18 -0
  167. package/out/renderer/node_modules/.pnpm/react-is@16.13.1/node_modules/react-is/index.js.map +1 -0
  168. package/out/renderer/node_modules/.pnpm/react-select@5.10.2_@types_react@17.0.93_react-dom@17.0.2_react@17.0.2__react@17.0.2/node_modules/react-select/dist/Select-ef7c0426.esm.js +2200 -0
  169. package/out/renderer/node_modules/.pnpm/react-select@5.10.2_@types_react@17.0.93_react-dom@17.0.2_react@17.0.2__react@17.0.2/node_modules/react-select/dist/Select-ef7c0426.esm.js.map +1 -0
  170. package/out/renderer/node_modules/.pnpm/react-select@5.10.2_@types_react@17.0.93_react-dom@17.0.2_react@17.0.2__react@17.0.2/node_modules/react-select/dist/index-641ee5b8.esm.js +992 -0
  171. package/out/renderer/node_modules/.pnpm/react-select@5.10.2_@types_react@17.0.93_react-dom@17.0.2_react@17.0.2__react@17.0.2/node_modules/react-select/dist/index-641ee5b8.esm.js.map +1 -0
  172. package/out/renderer/node_modules/.pnpm/react-select@5.10.2_@types_react@17.0.93_react-dom@17.0.2_react@17.0.2__react@17.0.2/node_modules/react-select/dist/react-select.esm.js +14 -0
  173. package/out/renderer/node_modules/.pnpm/react-select@5.10.2_@types_react@17.0.93_react-dom@17.0.2_react@17.0.2__react@17.0.2/node_modules/react-select/dist/react-select.esm.js.map +1 -0
  174. package/out/renderer/node_modules/.pnpm/react-select@5.10.2_@types_react@17.0.93_react-dom@17.0.2_react@17.0.2__react@17.0.2/node_modules/react-select/dist/useStateManager-7e1e8489.esm.js +56 -0
  175. package/out/renderer/node_modules/.pnpm/react-select@5.10.2_@types_react@17.0.93_react-dom@17.0.2_react@17.0.2__react@17.0.2/node_modules/react-select/dist/useStateManager-7e1e8489.esm.js.map +1 -0
  176. package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Enum.js +22 -0
  177. package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Enum.js.map +1 -0
  178. package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Middleware.js +30 -0
  179. package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Middleware.js.map +1 -0
  180. package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Parser.js +164 -0
  181. package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Parser.js.map +1 -0
  182. package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Serializer.js +37 -0
  183. package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Serializer.js.map +1 -0
  184. package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Tokenizer.js +245 -0
  185. package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Tokenizer.js.map +1 -0
  186. package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Utility.js +120 -0
  187. package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Utility.js.map +1 -0
  188. package/out/renderer/node_modules/.pnpm/use-isomorphic-layout-effect@1.2.1_@types_react@17.0.93_react@17.0.2/node_modules/use-isomorphic-layout-effect/dist/use-isomorphic-layout-effect.browser.esm.js +6 -0
  189. package/out/renderer/node_modules/.pnpm/use-isomorphic-layout-effect@1.2.1_@types_react@17.0.93_react@17.0.2/node_modules/use-isomorphic-layout-effect/dist/use-isomorphic-layout-effect.browser.esm.js.map +1 -0
  190. package/out/renderer/pod-monitoring.js +38 -11
  191. package/out/renderer/pod-monitoring.js.map +1 -1
  192. package/out/renderer/preferences/ai-shortcuts-preferences.js +12 -4
  193. package/out/renderer/preferences/ai-shortcuts-preferences.js.map +1 -1
  194. package/out/renderer/preferences/dashboard-preferences.js +20 -4
  195. package/out/renderer/preferences/dashboard-preferences.js.map +1 -1
  196. package/out/renderer/preferences/monitoring-preferences.js +141 -9
  197. package/out/renderer/preferences/monitoring-preferences.js.map +1 -1
  198. package/out/renderer/preferences/preferences.js +31 -7
  199. package/out/renderer/preferences/preferences.js.map +1 -1
  200. package/out/renderer/read-only.js +2 -2
  201. package/out/renderer/read-only.js.map +1 -1
  202. package/out/renderer/src/common/ai-terminal-context.js +51 -0
  203. package/out/renderer/src/common/ai-terminal-context.js.map +1 -0
  204. package/out/renderer/src/common/ai.js.map +1 -1
  205. package/out/renderer/src/common/cluster-icon-ipc.js +6 -0
  206. package/out/renderer/src/common/cluster-icon-ipc.js.map +1 -0
  207. package/out/renderer/src/common/cluster-icons.js +133 -0
  208. package/out/renderer/src/common/cluster-icons.js.map +1 -0
  209. package/out/renderer/src/common/dashboard.js +1 -1
  210. package/out/renderer/src/common/dashboard.js.map +1 -1
  211. package/out/renderer/src/common/date-time.js +11 -0
  212. package/out/renderer/src/common/date-time.js.map +1 -0
  213. package/out/renderer/src/common/monitoring-history.js +17 -0
  214. package/out/renderer/src/common/monitoring-history.js.map +1 -0
  215. package/out/renderer/src/common/monitoring-math.js +98 -0
  216. package/out/renderer/src/common/monitoring-math.js.map +1 -0
  217. package/out/renderer/src/common/resource-diagnostics.js +227 -0
  218. package/out/renderer/src/common/resource-diagnostics.js.map +1 -0
  219. package/out/renderer/src/common/settings-export.js.map +1 -1
  220. package/out/renderer/src/common/store/monitoring-preferences-store.js +30 -2
  221. package/out/renderer/src/common/store/monitoring-preferences-store.js.map +1 -1
  222. package/out/renderer/welcome.js +31 -7
  223. package/out/renderer/welcome.js.map +1 -1
  224. package/package.json +3 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-terminal-context.js","names":[],"sources":["../../src/renderer/ai-terminal-context.tsx"],"sourcesContent":["import { Renderer } from \"@freelensapp/extensions\";\nimport { useEffect, useState } from \"react\";\nimport { type AiTerminalSnapshot, sanitizeAiTerminalSnapshot } from \"../common/ai-terminal-context\";\nimport { formatDateTime } from \"../common/date-time\";\nimport { AiIcon } from \"./ai-icon\";\n\ntype TerminalBuffer = {\n length: number;\n baseY: number;\n cursorY: number;\n getLine(index: number): { isWrapped?: boolean; translateToString(trimRight?: boolean): string } | undefined;\n};\n\nexport function activeAiTerminal(clusterId?: string): string | undefined {\n if (!clusterId || Renderer.Catalog.activeCluster.get()?.metadata.uid !== clusterId) return;\n const prefix = \"dock-tab-content-for-\";\n for (const element of document.querySelectorAll<HTMLElement>(`[data-testid^=\"${prefix}\"]`)) {\n let visible = true;\n for (let node: HTMLElement | null = element; node; node = node.parentElement) {\n const style = getComputedStyle(node);\n if (\n node.hidden ||\n node.getAttribute(\"aria-hidden\") === \"true\" ||\n style.display === \"none\" ||\n style.visibility === \"hidden\" ||\n style.visibility === \"collapse\"\n ) {\n visible = false;\n break;\n }\n }\n const id = element.dataset.testid?.slice(prefix.length);\n if (!visible || !id || !Renderer.Component.terminalStore.isConnected(id)) continue;\n const api = Renderer.Component.terminalStore.getTerminalApi(id);\n if (api?.isReady && api.isConnected()) return id;\n }\n return;\n}\n\nexport function captureAiTerminal(clusterId?: string, expectedId?: string): AiTerminalSnapshot | undefined {\n const id = activeAiTerminal(clusterId);\n if (!id || (expectedId && id !== expectedId)) return;\n try {\n // [xterm] is a guarded host implementation detail with no public buffer accessor\n const terminal = Renderer.Component.terminalStore.getTerminal(id) as unknown as\n | {\n xterm?: { buffer?: { active?: TerminalBuffer } };\n }\n | undefined;\n const buffer = terminal?.xterm?.buffer?.active;\n if (!buffer || !Number.isSafeInteger(buffer.length) || buffer.length > 10_000 || buffer.length < 0) return;\n const end = buffer.length;\n if (!Number.isSafeInteger(end) || end < 0) return;\n const logical: string[] = [];\n let characters = 0;\n for (let index = 0; index < end; index++) {\n const line = buffer.getLine(index);\n if (!line || (index === 0 && line.isWrapped)) return;\n const text = line.translateToString(!buffer.getLine(index + 1)?.isWrapped);\n characters += text.length + 1;\n if (characters > 1_000_000) return;\n if (line.isWrapped && logical.length) logical[logical.length - 1] += text;\n else logical.push(text);\n }\n if (activeAiTerminal(clusterId) !== id) return;\n return sanitizeAiTerminalSnapshot({ text: logical.join(\"\\n\"), capturedAt: new Date().toISOString() });\n } catch {\n return;\n }\n}\n\nexport interface AiTerminalAttachment {\n clusterId: string;\n terminalId: string;\n}\n\nexport function AiTerminalContext({\n clusterId,\n attachment,\n onChange,\n disabled,\n}: {\n clusterId?: string;\n attachment?: AiTerminalAttachment;\n onChange(value: AiTerminalAttachment | undefined): void;\n disabled: boolean;\n}) {\n const [terminalId, setTerminalId] = useState(() => activeAiTerminal(clusterId));\n const [preview, setPreview] = useState<AiTerminalSnapshot>();\n const [unavailable, setUnavailable] = useState(false);\n useEffect(() => {\n const update = () => setTerminalId(activeAiTerminal(clusterId));\n update();\n const timer = window.setInterval(update, 500);\n return () => window.clearInterval(timer);\n }, [clusterId]);\n const attached = Boolean(attachment && attachment.clusterId === clusterId && attachment.terminalId === terminalId);\n useEffect(() => {\n if (!attached) {\n if (attachment) onChange(undefined);\n setPreview(undefined);\n return;\n }\n let stopped = false;\n let scheduled: number | undefined;\n let polling: number | undefined;\n let subscription: { dispose(): void } | undefined;\n const stop = () => {\n stopped = true;\n window.clearTimeout(scheduled);\n window.clearInterval(polling);\n subscription?.dispose();\n subscription = undefined;\n };\n const update = () => {\n if (stopped) return;\n scheduled = undefined;\n const snapshot = captureAiTerminal(clusterId, attachment?.terminalId);\n setUnavailable(!snapshot);\n if (!snapshot) {\n setPreview(undefined);\n if (activeAiTerminal(clusterId) !== attachment?.terminalId) {\n stop();\n onChange(undefined);\n }\n return;\n }\n setPreview((previous) =>\n previous?.text === snapshot.text && previous.truncated === snapshot.truncated ? previous : snapshot,\n );\n };\n update();\n if (stopped) return stop;\n try {\n const terminal = Renderer.Component.terminalStore.getTerminal(attachment!.terminalId) as unknown as\n | {\n xterm?: { onWriteParsed?: (listener: () => void) => { dispose(): void } };\n }\n | undefined;\n subscription = terminal?.xterm?.onWriteParsed?.(() => {\n if (!stopped && scheduled === undefined) scheduled = window.setTimeout(update, 250);\n });\n } catch {}\n if (!subscription) polling = window.setInterval(update, 1000);\n return stop;\n }, [attached, attachment, clusterId, onChange]);\n return (\n <div className=\"power-ai-terminal-context\" style={{ fontSize: 11 }}>\n <button\n type=\"button\"\n aria-label=\"Attach terminal output\"\n aria-pressed={attached}\n style={{\n position: \"absolute\",\n top: 8,\n right: 8,\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: 26,\n height: 26,\n minHeight: 26,\n padding: 0,\n color: \"var(--textColorSecondary)\",\n borderColor: \"var(--borderFaintColor)\",\n background: attached ? \"color-mix(in srgb, var(--textColorPrimary) 8%, transparent)\" : \"transparent\",\n }}\n disabled={disabled || !terminalId}\n title={\n attached\n ? \"Detach terminal output from this question\"\n : terminalId\n ? \"Attach terminal output to this question\"\n : \"Open a connected terminal in this cluster\"\n }\n onClick={() => {\n if (attached) {\n onChange(undefined);\n setPreview(undefined);\n return;\n }\n const snapshot = captureAiTerminal(clusterId, terminalId);\n setUnavailable(!snapshot);\n if (!snapshot || !clusterId || !terminalId) return;\n setPreview(snapshot);\n onChange({ clusterId, terminalId });\n }}\n >\n <AiIcon material=\"terminal\" size={16} />\n </button>\n {attached && preview && (\n <details style={{ padding: \"0 16px 4px\", margin: 0 }}>\n <summary>\n Terminal · {preview.text.split(\"\\n\").length} rows{preview.truncated ? \" · truncated\" : \"\"}\n </summary>\n <p>\n Preview captured <span style={{ whiteSpace: \"pre-wrap\" }}>{formatDateTime(preview.capturedAt)}</span> ·\n captured again when sent · up to 300 rows / 32 KiB · Common credentials masked. Review before sending.\n </p>\n <pre style={{ maxHeight: 160, overflow: \"auto\", whiteSpace: \"pre-wrap\" }}>{preview.text}</pre>\n <p>The attachment is not stored in chat history. Assistant replies may quote it.</p>\n </details>\n )}\n {unavailable && (\n <div role=\"status\" style={{ padding: \"4px 16px 8px\" }}>\n Terminal output is unavailable or exceeds the safe capture limit\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -16,6 +16,7 @@ const require_ai_message = require("./ai-message.js");
16
16
  const require_ai_provider_icon = require("./ai-provider-icon.js");
17
17
  const require_ai_resize = require("./ai-resize.js");
18
18
  const require_ai_shortcuts$1 = require("./ai-shortcuts.js");
19
+ const require_ai_terminal_context = require("./ai-terminal-context.js");
19
20
  let electron = require("electron");
20
21
  //#region src/renderer/ai.tsx
21
22
  function readAiContext() {
@@ -80,6 +81,7 @@ function hasAiOverlay() {
80
81
  var styles = `
81
82
  @keyframes power-ai-spin { to { transform: rotate(360deg); } }
82
83
  @keyframes power-ai-dot { 0%, 80%, 100% { opacity: .25; } 40% { opacity: 1; } }
84
+ body:has(.AddRemoveButtons .remove-button:not([data-freelens-power-read-only])) .power-ai-launcher { display: none; }
83
85
  .power-ai-read-activity > span { display: inline-flex; align-items: center; gap: 4px; }
84
86
  .power-ai-read-activity [data-status="reading"] .Icon { animation: power-ai-spin 1.2s linear infinite; }
85
87
  .power-ai-thinking { margin: 12px 16px 18px; line-height: 1.5; color: var(--textColorSecondary); }
@@ -138,6 +140,7 @@ var styles = `
138
140
  :root .power-ai-panel header button.power-ai-pin[aria-pressed="true"] { color: var(--primary); }
139
141
  .power-ai-panel header > button { flex-shrink: 0; }
140
142
  .power-ai-panel form { position: relative; flex-shrink: 0; margin: 0 16px 16px; border: 1px solid var(--borderFaintColor); border-radius: 12px; background: var(--mainBackground); transition: border-color 160ms ease; }
143
+ .power-ai-panel form > .power-ai-context-preview { padding: 8px 48px 4px 16px !important; min-height: 34px; margin: 0; box-sizing: border-box; }
141
144
  .power-ai-panel form:focus-within { border-color: var(--primary); }
142
145
  .power-ai-message > strong { display: flex; align-items: center; gap: 8px; font-size: 12px; font-weight: 500; color: var(--textColorSecondary); margin-bottom: 10px; }
143
146
  .power-ai-message-assistant { border-color: transparent; background: transparent; }
@@ -187,6 +190,7 @@ var AiChat = require__global_external_mobx_react.observer(({ isClusterDocument }
187
190
  const [viewportWidth, setViewportWidth] = require__global_external_react.useState(window.innerWidth);
188
191
  const [launcherHidden, setLauncherHidden] = require__global_external_react.useState(false);
189
192
  const [draft, setDraft] = require__global_external_react.useState("");
193
+ const [terminalAttachment, setTerminalAttachment] = require__global_external_react.useState();
190
194
  const [suggestionIndex, setSuggestionIndex] = require__global_external_react.useState(0);
191
195
  const [dismissedDraft, setDismissedDraft] = require__global_external_react.useState();
192
196
  const suggestions = /^\/[^\s]*$/.test(draft) && dismissedDraft !== draft ? require_ai_shortcuts_store.AiShortcutsStore.getInstanceOrCreate().shortcuts.filter((shortcut) => `${shortcut.command} ${shortcut.label}`.toLowerCase().includes(draft.slice(1).toLowerCase())) : [];
@@ -333,21 +337,58 @@ var AiChat = require__global_external_mobx_react.observer(({ isClusterDocument }
333
337
  return () => document.removeEventListener("click", onOutsideClick, true);
334
338
  }, [open, pinned]);
335
339
  require__global_external_react.useEffect(() => {
336
- const toggle = (event) => {
337
- const mac = /Mac|iPhone|iPad/.test(navigator.platform);
338
- if (event.repeat || event.isComposing || event.keyCode === 229 || event.altKey || !event.shiftKey || (mac ? !event.metaKey || event.ctrlKey : !event.ctrlKey || event.metaKey) || event.code !== "KeyY" || !preferences.enabled || !isClusterDocument() || hasAiOverlay()) return;
339
- event.preventDefault();
340
- event.stopPropagation();
341
- event.stopImmediatePropagation();
340
+ const heldKeys = /* @__PURE__ */ new Set();
341
+ let shiftDownAt;
342
+ let lastTapAt;
343
+ const reset = () => {
344
+ shiftDownAt = void 0;
345
+ lastTapAt = void 0;
346
+ };
347
+ const onKeyDown = (event) => {
348
+ if (event.key !== "Shift") heldKeys.add(event.code || event.key);
349
+ if (event.key !== "Shift" || event.repeat || event.isComposing || event.keyCode === 229 || event.altKey || event.ctrlKey || event.metaKey || heldKeys.size > 0 || shiftDownAt !== void 0) {
350
+ reset();
351
+ return;
352
+ }
353
+ shiftDownAt = performance.now();
354
+ };
355
+ const onKeyUp = (event) => {
356
+ if (event.key === "Meta") {
357
+ heldKeys.clear();
358
+ reset();
359
+ return;
360
+ }
361
+ heldKeys.delete(event.code || event.key);
362
+ const now = performance.now();
363
+ if (event.key !== "Shift" || shiftDownAt === void 0 || now - shiftDownAt > 400 || event.isComposing || event.altKey || event.ctrlKey || event.metaKey || !preferences.enabled || !isClusterDocument() || hasAiOverlay()) {
364
+ reset();
365
+ return;
366
+ }
367
+ shiftDownAt = void 0;
368
+ if (lastTapAt === void 0 || now - lastTapAt > 400) {
369
+ lastTapAt = now;
370
+ return;
371
+ }
372
+ reset();
342
373
  setContext(readAiContext());
343
374
  setOpen((value) => !value);
344
375
  };
345
- window.addEventListener("keydown", toggle, true);
346
- return () => window.removeEventListener("keydown", toggle, true);
376
+ window.addEventListener("keydown", onKeyDown, true);
377
+ window.addEventListener("keyup", onKeyUp, true);
378
+ const onBlur = () => {
379
+ heldKeys.clear();
380
+ reset();
381
+ };
382
+ window.addEventListener("blur", onBlur);
383
+ return () => {
384
+ window.removeEventListener("keydown", onKeyDown, true);
385
+ window.removeEventListener("keyup", onKeyUp, true);
386
+ window.removeEventListener("blur", onBlur);
387
+ };
347
388
  }, [preferences, isClusterDocument]);
348
389
  const availablePanelWidth = Math.max(1, viewportWidth - Math.max(0, launcherLeft - 16));
349
390
  const panelWidth = require_ai_resize.clampAiPanelWidth(preferences.chatPanelWidth ?? 560, availablePanelWidth);
350
- const shortcutLabel = /Mac|iPhone|iPad/.test(navigator.platform) ? "⌘⇧Y" : "Ctrl+Shift+Y";
391
+ const shortcutLabel = "Shift, Shift";
351
392
  const key = context.clusterId ?? "global";
352
393
  const messages = preferences.conversations[key] ?? [];
353
394
  const busy = pending.includes(key);
@@ -366,6 +407,31 @@ var AiChat = require__global_external_mobx_react.observer(({ isClusterDocument }
366
407
  const element = messagesElement.current;
367
408
  if (element && open) element.scrollTop = element.scrollHeight;
368
409
  }, [open, key]);
410
+ require__global_external_react.useEffect(() => {
411
+ if (!terminalAttachment) return;
412
+ const update = () => {
413
+ if (require_ai_terminal_context.activeAiTerminal(terminalAttachment.clusterId) !== terminalAttachment.terminalId) setTerminalAttachment(void 0);
414
+ };
415
+ update();
416
+ const timer = window.setInterval(update, 500);
417
+ const observer = new MutationObserver(update);
418
+ observer.observe(document.body, {
419
+ childList: true,
420
+ subtree: true,
421
+ attributes: true,
422
+ attributeFilter: [
423
+ "class",
424
+ "style",
425
+ "hidden",
426
+ "aria-hidden",
427
+ "data-testid"
428
+ ]
429
+ });
430
+ return () => {
431
+ window.clearInterval(timer);
432
+ observer.disconnect();
433
+ };
434
+ }, [terminalAttachment, context.clusterId]);
369
435
  if (!preferences.enabled || !isClusterDocument() || coveredByOverlay) return null;
370
436
  const send = async (starter) => {
371
437
  const question = require_ai_shortcuts.expandAiShortcut((starter ?? draft).trim(), require_ai_shortcuts_store.AiShortcutsStore.getInstanceOrCreate().shortcuts);
@@ -379,6 +445,13 @@ var AiChat = require__global_external_mobx_react.observer(({ isClusterDocument }
379
445
  setContext(requestContext);
380
446
  return;
381
447
  }
448
+ const terminalSnapshot = terminalAttachment?.clusterId === requestContext.clusterId ? require_ai_terminal_context.captureAiTerminal(requestContext.clusterId, terminalAttachment?.terminalId) : void 0;
449
+ if (terminalAttachment && !terminalSnapshot) {
450
+ setTerminalAttachment(void 0);
451
+ setError("The attached terminal changed or is unavailable. Attach it again before sending.");
452
+ return;
453
+ }
454
+ setTerminalAttachment(void 0);
382
455
  following.current = true;
383
456
  const next = [...messages, {
384
457
  role: "user",
@@ -407,6 +480,7 @@ var AiChat = require__global_external_mobx_react.observer(({ isClusterDocument }
407
480
  return tail;
408
481
  }, []),
409
482
  context: requestContext,
483
+ ...terminalSnapshot ? { terminalSnapshot } : {},
410
484
  systemPrompt: [preferences.systemPrompt, requestContext.clusterId ? preferences.clusterPrompt : ""].filter(Boolean).join("\n\n"),
411
485
  model: preferences.model,
412
486
  speed: preferences.speed,
@@ -525,6 +599,7 @@ var AiChat = require__global_external_mobx_react.observer(({ isClusterDocument }
525
599
  "aria-label": "New chat",
526
600
  title: "Clear this conversation and start a new chat",
527
601
  onClick: () => {
602
+ setTerminalAttachment(void 0);
528
603
  preferences.setMessages(key, []);
529
604
  setStopped((keys) => keys.filter((entry) => entry !== key));
530
605
  setActivity({
@@ -711,6 +786,12 @@ var AiChat = require__global_external_mobx_react.observer(({ isClusterDocument }
711
786
  }, shortcut.id))
712
787
  }),
713
788
  /* @__PURE__ */ require_jsx_runtime.jsx(require_ai_extras$1.AiContextPreview, { context: require_ai_extras.attachedAiContext(context) }),
789
+ /* @__PURE__ */ require_jsx_runtime.jsx(require_ai_terminal_context.AiTerminalContext, {
790
+ clusterId: context.clusterId,
791
+ attachment: terminalAttachment,
792
+ onChange: setTerminalAttachment,
793
+ disabled: busy
794
+ }),
714
795
  /* @__PURE__ */ require_jsx_runtime.jsx("textarea", {
715
796
  ref: composer,
716
797
  "aria-controls": suggestions.length ? "power-ai-commands" : void 0,
@@ -1 +1 @@
1
- {"version":3,"file":"ai.js","names":[],"sources":["../../src/renderer/ai.tsx"],"sourcesContent":["import { Renderer } from \"@freelensapp/extensions\";\nimport { ipcRenderer } from \"electron\";\nimport { autorun } from \"mobx\";\nimport { observer } from \"mobx-react\";\nimport { type CSSProperties, useEffect, useRef, useState } from \"react\";\nimport ReactDOM from \"react-dom\";\nimport { AI_CHAT_CHANNEL, AI_READ_ACTIVITY_CHANNEL, type AiReadActivity } from \"../common/ai\";\nimport { AI_CANCEL_CHANNEL, attachedAiContext, normalizeAiReferences } from \"../common/ai-extras\";\nimport { expandAiShortcut } from \"../common/ai-shortcuts\";\nimport { type AiMessage, AiPreferencesStore } from \"../common/store/ai-preferences-store\";\nimport { AiShortcutsStore } from \"../common/store/ai-shortcuts-store\";\nimport { AiCopyAnswer } from \"./ai-copy-answer\";\nimport { AiContextPreview, AiResourceReferences } from \"./ai-extras\";\nimport { AiIcon } from \"./ai-icon\";\nimport { AiMessageContent } from \"./ai-message\";\nimport { AiProviderIcon } from \"./ai-provider-icon\";\nimport { AiResizeHandle, clampAiPanelWidth, DEFAULT_AI_PANEL_WIDTH } from \"./ai-resize\";\nimport { AiStarterPrompts } from \"./ai-shortcuts\";\n\nexport interface AiScreenContext {\n clusterId?: string;\n screen?: string;\n resource?: { kind?: string; namespace?: string; name?: string };\n}\n\nexport function readAiContext(): AiScreenContext {\n const clusterId = Renderer.Catalog.activeCluster.get()?.metadata.uid;\n const screen = window.location.pathname;\n const details = new URLSearchParams(window.location.search).get(\"kube-details\");\n const match =\n details?.match(/^\\/api(?:\\/v\\d+)?\\/namespaces\\/([^/]+)\\/([^/]+)\\/([^/]+)$/) ??\n details?.match(/^\\/apis\\/[^/]+\\/[^/]+\\/namespaces\\/([^/]+)\\/([^/]+)\\/([^/]+)$/);\n const clusterResource =\n details?.match(/^\\/api\\/[^/]+\\/([^/]+)\\/([^/]+)$/) ?? details?.match(/^\\/apis\\/[^/]+\\/[^/]+\\/([^/]+)\\/([^/]+)$/);\n const resource = match\n ? { namespace: match[1], kind: match[2], name: match[3] }\n : clusterResource\n ? { kind: clusterResource[1], name: clusterResource[2] }\n : undefined;\n return { clusterId, screen, ...(resource ? { resource } : {}) };\n}\n\nexport function isAiClusterDocument(): boolean {\n return window.top !== window && Boolean(Renderer.Catalog.activeCluster.get());\n}\n\nexport function aiLauncherBottom(): number {\n const dock = document.querySelector<HTMLElement>(\".Dock\");\n if (!dock) return 16;\n const rect = dock.getBoundingClientRect();\n const style = window.getComputedStyle(dock);\n if (\n dock.hidden ||\n style.display === \"none\" ||\n style.visibility === \"hidden\" ||\n rect.width <= 0 ||\n rect.height <= 0 ||\n rect.top <= 0 ||\n rect.top >= window.innerHeight\n )\n return 16;\n return Math.max(16, window.innerHeight - rect.top + 16);\n}\n\nexport function aiLauncherLeft(): number {\n const sidebar = document.querySelector<HTMLElement>('[data-testid=\"cluster-sidebar\"], .Sidebar');\n const dock = document.querySelector<HTMLElement>(\".Dock\");\n let contentLeft = 0;\n for (const [element, edge] of [\n [sidebar, \"right\"],\n [dock, \"left\"],\n ] as const) {\n if (!element || element.hidden) continue;\n const style = window.getComputedStyle(element);\n const rect = element.getBoundingClientRect();\n if (style.display === \"none\" || style.visibility === \"hidden\" || rect.width <= 0) continue;\n const value = rect[edge];\n if (Number.isFinite(value) && value >= 0 && value < window.innerWidth - 80)\n contentLeft = Math.max(contentLeft, value);\n }\n return contentLeft + 16;\n}\n\nexport function hasAiResourceDetails(): boolean {\n if (new URLSearchParams(window.location.search).get(\"kube-details\")) return true;\n return Array.from(\n document.querySelectorAll<HTMLElement>(\".Drawer.KubeObjectDetails, .Drawer.ReleaseDetails, .DetailsDrawer\"),\n ).some((element) => {\n const style = window.getComputedStyle(element);\n const rect = element.getBoundingClientRect();\n return (\n !element.hidden && style.display !== \"none\" && style.visibility !== \"hidden\" && rect.width > 0 && rect.height > 0\n );\n });\n}\n\nexport function hasAiOverlay(): boolean {\n return Array.from(document.querySelectorAll<HTMLElement>('[role=\"dialog\"], dialog[open], .Dialog')).some(\n (element) => {\n const style = window.getComputedStyle(element);\n return !element.hidden && style.display !== \"none\" && style.visibility !== \"hidden\";\n },\n );\n}\n\nconst styles = `\n@keyframes power-ai-spin { to { transform: rotate(360deg); } }\n@keyframes power-ai-dot { 0%, 80%, 100% { opacity: .25; } 40% { opacity: 1; } }\n.power-ai-read-activity > span { display: inline-flex; align-items: center; gap: 4px; }\n.power-ai-read-activity [data-status=\"reading\"] .Icon { animation: power-ai-spin 1.2s linear infinite; }\n.power-ai-thinking { margin: 12px 16px 18px; line-height: 1.5; color: var(--textColorSecondary); }\n.power-ai-dots > span { animation: power-ai-dot 1.3s ease-in-out infinite; }\n.power-ai-dots > span:nth-child(2) { animation-delay: .15s; }\n.power-ai-dots > span:nth-child(3) { animation-delay: .3s; }\n@media (prefers-reduced-motion: reduce) { .power-ai-read-activity [data-status=\"reading\"] .Icon, .power-ai-dots > span { animation: none; } }\n@keyframes power-ai-enter { from { transform: translateX(100%); } to { transform: translateX(0); } }\n:root .power-ai-launcher { position: fixed; bottom: 16px; left: auto; right: 16px; z-index: 100; display: inline-flex; align-items: center; gap: 6px; min-width: 0; min-height: 0; height: 34px; border: 1px solid var(--primary, #5896ff); border-radius: 24px; padding: 0 13px; background: var(--contentColor, #242424); color: var(--textColorAccent); box-shadow: 0 3px 12px #0003; font: inherit; font-size: 12px; font-weight: 500; line-height: 1; cursor: pointer; transition: opacity 180ms ease, background-color 140ms ease, box-shadow 140ms ease, transform 180ms ease; }\n.power-ai-overview-actions { position: relative; z-index: 5; height: 0; min-height: 0; flex: 0 0 0; pointer-events: none; }\n.power-ai-overview-actions + [data-testid=\"cluster-overview-page\"] [data-monitoring-summaries] { --power-monitoring-summary-top: 56px; }\n.power-ai-overview-actions button { transition: background-color 160ms ease, border-color 160ms ease, color 160ms ease, box-shadow 160ms ease; position: absolute; top: 12px; right: 12px; pointer-events: auto; box-shadow: 0 2px 8px #0002; display: inline-flex; flex: 0 0 auto; width: auto; align-items: center; gap: 6px; min-height: 32px; padding: 6px 12px; font: inherit; font-size: 12px; border: 1px solid var(--borderFaintColor); border-radius: 10px; color: var(--textColorPrimary); background: var(--contentColor); cursor: pointer; }\n.power-ai-overview-actions button:hover { border-color: var(--primary); color: var(--textColorAccent); background: var(--contentColor); }\n.power-ai-overview-actions button:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }\n.power-ai-launcher.power-ai-launcher-hidden { opacity: 0; transform: translateY(8px); pointer-events: none; }\n.power-ai-launcher .Icon { color: inherit; }\n.power-ai-launcher:hover { background: color-mix(in srgb, var(--primary, #5896ff) 12%, var(--contentColor, #242424)); box-shadow: 0 4px 12px #0003; transform: translateY(-1px); }\n.power-ai-launcher:active { transform: translateY(0); box-shadow: 0 2px 6px #0002; }\n@media (prefers-reduced-motion: reduce) { :root .power-ai-launcher { transition: none; } .power-ai-launcher:hover, .power-ai-launcher:active { transform: none; } }\n.power-ai-launcher:focus-visible { outline: 2px solid var(--primary, #5896ff); outline-offset: 3px; }\n.power-ai-panel { position: fixed; right: 0; top: 0; bottom: 0; width: min(560px, 100vw); z-index: 10001; display: flex; flex-direction: column; background: var(--contentColor, #242424); color: var(--textColorAccent, white); animation: power-ai-enter 160ms ease-out; border-left: 1px solid var(--borderFaintColor); box-shadow: -4px 0 24px #0004; }\n.power-ai-resize-handle { position: absolute; left: -4px; top: 0; bottom: 0; width: 8px; z-index: 2; cursor: col-resize; touch-action: none; }\n.power-ai-resize-handle:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }\n.power-ai-panel header { padding: 16px; display: flex; gap: 10px; flex-shrink: 0; }\n.power-ai-panel header { border-bottom: 1px solid var(--borderFaintColor); justify-content: space-between; align-items: center; }\n.power-ai-messages { overflow: auto; flex: 1; min-height: 0; padding: 24px 16px; font-size: var(--power-ai-font-size, 14px); line-height: 1.65; overscroll-behavior: contain; }\n.power-ai-message { overflow-wrap: anywhere; padding: 14px 16px; margin-bottom: 20px; color: var(--textColorAccent); border: 1px solid var(--borderFaintColor); border-radius: 8px; }\n.power-ai-panel button { padding: 7px 10px; border: 1px solid var(--borderFaintColor); border-radius: 8px; background: var(--contentColor); color: var(--textColorPrimary); cursor: pointer; }\n:root .power-ai-panel header button:is(.power-ai-close, .power-ai-pin) { width: 30px; height: 30px; padding: 0; display: inline-flex; align-items: center; justify-content: center; border: 0; border-radius: 6px; background: transparent; color: var(--textColorSecondary); }\n:root .power-ai-panel header button:is(.power-ai-close, .power-ai-pin):not(:disabled):not(.disabled):hover { color: var(--primary); background: color-mix(in srgb, var(--primary) 10%, transparent); }\n:root .power-ai-panel header button:is(.power-ai-close, .power-ai-pin):focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }\n:root .power-ai-panel button.power-ai-copy-answer { width: 24px; height: 24px; padding: 0; margin-left: auto; flex-shrink: 0; justify-content: center; border: 0; background: transparent; color: var(--textColorSecondary); }\n:root .power-ai-panel button.power-ai-copy-answer:not(:disabled):not(.disabled):hover { color: var(--primary); background: color-mix(in srgb, var(--primary) 10%, transparent); }\n:root .power-ai-panel button.power-ai-copy-answer:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }\n.power-ai-cancellation { display: flex; align-items: center; gap: 6px; }\n:root .power-ai-panel button.power-ai-dismiss { width: 24px; height: 24px; padding: 0; justify-content: center; border: 0; border-radius: 6px; background: transparent; color: var(--textColorSecondary); }\n:root .power-ai-panel button.power-ai-dismiss:hover { color: var(--primary); background: color-mix(in srgb, var(--primary) 10%, transparent); }\n:root .power-ai-panel button.power-ai-dismiss:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }\n.power-ai-panel button:disabled { opacity: 0.5; cursor: default; }\n .power-ai-panel textarea { display: block; width: 100%; box-sizing: border-box; min-width: 0; min-height: 64px; max-height: 180px; field-sizing: content; padding: 12px 16px 6px; border: 0; border-radius: 12px; background: transparent; color: var(--textColorAccent); font: inherit; font-size: var(--power-ai-font-size, 14px); line-height: 1.5; resize: none; }\n.power-ai-panel textarea::placeholder { color: var(--textColorSecondary); opacity: 1; }\n.power-ai-panel textarea:focus { outline: none; }\n.power-ai-composer-footer { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 4px 10px 10px 16px; }\n.power-ai-composer-footer > span { color: var(--textColorSecondary); font-size: 11px; line-height: 1.5; }\n:root .power-ai-panel form button[type=\"submit\"] { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 34px; width: 34px; height: 34px; padding: 0; border-radius: 10px; }\n:root .power-ai-panel form button[type=\"submit\"]:not(:disabled):not(.disabled) { background-color: var(--primary); border-color: var(--primary); color: white; }\n:root .power-ai-panel form button[type=\"submit\"]:not(:disabled):not(.disabled):hover { background-color: color-mix(in srgb, var(--primary) 88%, white 12%); border-color: color-mix(in srgb, var(--primary) 88%, white 12%); color: white; }\n:root .power-ai-panel form button[type=\"submit\"]:focus-visible { outline: 2px solid var(--primary); outline-offset: 3px; }\n:root .power-ai-panel form button[type=\"submit\"]:disabled { background-color: var(--contentColor); border-color: var(--borderFaintColor); color: var(--textColorSecondary); }\n.power-ai-message-user { border-color: color-mix(in srgb, var(--primary) 28%, var(--borderFaintColor)); background: color-mix(in srgb, var(--primary) 7%, var(--mainBackground)); }\n.power-ai-context { padding: 10px 20px; line-height: 1.5; border-bottom: 1px solid var(--borderFaintColor); font-size: 12px; color: var(--textColorSecondary); overflow-wrap: anywhere; }\n.power-ai-title, .power-ai-panel button { display: inline-flex; align-items: center; gap: 6px; }\n.power-ai-title { margin-right: auto; white-space: nowrap; color: var(--textColorAccent); }\n.power-ai-brand { display: inline-flex; align-items: center; gap: 6px; color: var(--primary); }\n.power-ai-brand .Icon { color: inherit; }\n:root .power-ai-panel header button.power-ai-pin[aria-pressed=\"true\"] { color: var(--primary); }\n.power-ai-panel header > button { flex-shrink: 0; }\n.power-ai-panel form { position: relative; flex-shrink: 0; margin: 0 16px 16px; border: 1px solid var(--borderFaintColor); border-radius: 12px; background: var(--mainBackground); transition: border-color 160ms ease; }\n.power-ai-panel form:focus-within { border-color: var(--primary); }\n.power-ai-message > strong { display: flex; align-items: center; gap: 8px; font-size: 12px; font-weight: 500; color: var(--textColorSecondary); margin-bottom: 10px; }\n.power-ai-message-assistant { border-color: transparent; background: transparent; }\n.power-ai-markdown { line-height: 1.65; font-size: var(--power-ai-font-size, 14px); color: var(--textColorAccent); }\n.power-ai-markdown p { margin: 0 0 14px; white-space: pre-wrap; }\n.power-ai-markdown p:last-child { margin-bottom: 0; }\n.power-ai-markdown ul, .power-ai-markdown ol { padding-left: 24px; margin: 10px 0 16px; }\n.power-ai-markdown ul { list-style: disc; }\n.power-ai-markdown ol { list-style: decimal; }\n.power-ai-markdown li { margin: 5px 0; }\n.power-ai-markdown li > ul, .power-ai-markdown li > ol { margin: 6px 0; }\n.power-ai-markdown li > p { margin-bottom: 6px; }\n.power-ai-markdown :is(h1, h2, h3, h4, h5, h6) { color: var(--textColorAccent); font-weight: 600; line-height: 1.4; margin: 24px 0 12px; }\n.power-ai-markdown :is(h1, h2, h3, h4, h5, h6):first-child { margin-top: 0; }\n.power-ai-markdown h1 { font-size: 1.43em; }\n.power-ai-markdown h2 { font-size: 1.29em; }\n.power-ai-markdown h3 { font-size: 1.14em; }\n.power-ai-markdown :is(h4, h5, h6) { font-size: 1em; }\n.power-ai-markdown blockquote { margin: 16px 0; padding: 4px 14px; border-left: 3px solid var(--borderColor); color: var(--textColorSecondary); }\n.power-ai-markdown blockquote > p:last-child { margin-bottom: 0; }\n.power-ai-markdown table { display: block; max-width: 100%; overflow-x: auto; margin: 16px 0; border-collapse: collapse; font-size: max(10px, calc(var(--power-ai-font-size, 14px) - 1px)); }\n.power-ai-markdown th, .power-ai-markdown td { padding: 9px 12px; border: 1px solid var(--borderFaintColor); text-align: left; }\n.power-ai-markdown th { font-weight: 600; background: color-mix(in srgb, var(--textColorAccent) 5%, transparent); }\n.power-ai-markdown a { color: var(--primary); text-decoration: underline; text-underline-offset: 2px; }\n.power-ai-markdown hr { margin: 20px 0; border: 0; border-top: 1px solid var(--borderFaintColor); }\n.power-ai-markdown code { font-family: var(--font-monospace, monospace); font-size: max(10px, calc(var(--power-ai-font-size, 14px) - 1px)); background: color-mix(in srgb, var(--textColorAccent) 8%, transparent); padding: 1px 4px; border-radius: 4px; }\n.power-ai-code { margin: 12px 0; border: 1px solid var(--borderFaintColor); border-radius: 8px; overflow: hidden; background: var(--mainBackground); }\n.power-ai-code-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 6px 8px; border-bottom: 1px solid var(--borderFaintColor); color: var(--textColorSecondary); font-size: 11px; }\n.power-ai-code-toolbar > div { display: flex; gap: 4px; }\n.power-ai-code-toolbar button { padding: 4px 6px; font-size: 11px; }\n.power-ai-code pre { margin: 0; padding: 12px; overflow-x: auto; white-space: pre; }\n.power-ai-code pre code { padding: 0; background: transparent; }\n.power-ai-code-hint, .power-ai-code-feedback:not(:empty) { padding: 0 12px 10px; color: var(--textColorSecondary); font-size: 11px; }\n.power-ai-autocomplete { position: absolute; bottom: calc(100% + 8px); left: 0; right: 0; max-height: 240px; overflow-y: auto; padding: 6px; border: 1px solid var(--borderColor); border-radius: 10px; background: var(--contentColor); box-shadow: 0 4px 16px #0003; }\n.power-ai-autocomplete button { display: flex; width: 100%; justify-content: space-between; gap: 12px; border: 0; text-align: left; }\n.power-ai-autocomplete button[aria-selected=\"true\"] { background: color-mix(in srgb, var(--primary) 14%, var(--contentColor)); color: var(--textColorAccent); }\n.power-ai-autocomplete button > span:last-child { color: var(--textColorSecondary); font-size: 12px; }\n@media (prefers-reduced-motion: reduce) { .power-ai-panel { animation: none; } }\n`;\n\nconst AiChat = observer(({ isClusterDocument }: { isClusterDocument: () => boolean }) => {\n const preferences = AiPreferencesStore.getInstanceOrCreate<AiPreferencesStore>();\n const [open, setOpen] = useState(false);\n const [pinned, setPinned] = useState(false);\n const [launcherBottom, setLauncherBottom] = useState(aiLauncherBottom);\n const [launcherLeft, setLauncherLeft] = useState(aiLauncherLeft);\n const [resourceDetailsOpen, setResourceDetailsOpen] = useState(hasAiResourceDetails);\n const [viewportWidth, setViewportWidth] = useState(window.innerWidth);\n const [launcherHidden, setLauncherHidden] = useState(false);\n const [draft, setDraft] = useState(\"\");\n const [suggestionIndex, setSuggestionIndex] = useState(0);\n const [dismissedDraft, setDismissedDraft] = useState<string>();\n const suggestions =\n /^\\/[^\\s]*$/.test(draft) && dismissedDraft !== draft\n ? AiShortcutsStore.getInstanceOrCreate<AiShortcutsStore>().shortcuts.filter((shortcut) =>\n `${shortcut.command} ${shortcut.label}`.toLowerCase().includes(draft.slice(1).toLowerCase()),\n )\n : [];\n const dismissSuggestions = useRef<() => boolean>(() => false);\n dismissSuggestions.current = () => {\n if (!suggestions.length) return false;\n setDismissedDraft(draft);\n return true;\n };\n const following = useRef(true);\n const composer = useRef<HTMLTextAreaElement>(null);\n const selectSuggestion = (index: number) => {\n const shortcut = suggestions[index];\n if (!shortcut) return;\n setDraft(`/${shortcut.command} `);\n setSuggestionIndex(0);\n composer.current?.focus();\n };\n const [context, setContext] = useState(readAiContext);\n const [pending, setPending] = useState<string[]>([]);\n const [error, setError] = useState(\"\");\n const [stopped, setStopped] = useState<string[]>([]);\n const activeRequests = useRef(new Map<string, string>());\n const [activity, setActivity] = useState<{\n key: string;\n reads: { method: AiReadActivity[\"method\"]; status: \"reading\" | \"ok\" | \"unavailable\" }[];\n }>({ key: \"\", reads: [] });\n const clusterReview = useRef<() => void>(() => {});\n const messagesElement = useRef<HTMLDivElement>(null);\n const [coveredByOverlay, setCoveredByOverlay] = useState(hasAiOverlay);\n useEffect(() => {\n let observedElements: Element[] = [];\n const resizeObserver =\n typeof ResizeObserver === \"undefined\"\n ? undefined\n : new ResizeObserver(() => {\n setLauncherBottom(aiLauncherBottom());\n setLauncherLeft(aiLauncherLeft());\n });\n const updateDock = () => {\n setViewportWidth(window.innerWidth);\n setLauncherBottom(aiLauncherBottom());\n setLauncherLeft(aiLauncherLeft());\n const elements = [\n document.querySelector(\".Dock\"),\n document.querySelector('[data-testid=\"cluster-sidebar\"], .Sidebar'),\n ].filter((element): element is Element => !!element);\n if (\n elements.length !== observedElements.length ||\n elements.some((element, index) => element !== observedElements[index])\n ) {\n resizeObserver?.disconnect();\n observedElements = elements;\n for (const element of elements) resizeObserver?.observe(element);\n }\n };\n const update = () => {\n updateDock();\n setContext(readAiContext());\n setResourceDetailsOpen(hasAiResourceDetails());\n setCoveredByOverlay(hasAiOverlay());\n };\n const onActivity = (_event: unknown, value: unknown) => {\n if (!value || typeof value !== \"object\") return;\n const entry = value as { requestId?: string; method?: string; status?: string };\n const requestKey = activeRequests.current.get(entry.requestId ?? \"\");\n if (\n !requestKey ||\n requestKey !== readAiContext().clusterId ||\n ![\"pods\", \"nodes\", \"resources\", \"logs\"].includes(entry.method ?? \"\") ||\n ![\"reading\", \"ok\", \"unavailable\"].includes(entry.status ?? \"\")\n )\n return;\n const read = {\n method: entry.method as AiReadActivity[\"method\"],\n status: entry.status as \"reading\" | \"ok\" | \"unavailable\",\n };\n setActivity((previous) => ({\n key: requestKey,\n reads: [\n ...(previous.key === requestKey ? previous.reads.filter((item) => item.method !== read.method) : []),\n read,\n ],\n }));\n };\n ipcRenderer.on(AI_READ_ACTIVITY_CHANNEL, onActivity);\n window.addEventListener(\"resize\", updateDock);\n window.addEventListener(\"popstate\", update);\n update();\n const timer = window.setInterval(update, 500);\n const observer = new MutationObserver(update);\n observer.observe(document.body, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: [\"class\", \"style\", \"hidden\", \"open\"],\n });\n window.addEventListener(\"power-ai-open\", updateAndOpen);\n function updateAndOpen() {\n update();\n setOpen(true);\n clusterReview.current();\n }\n return () => {\n window.removeEventListener(\"resize\", updateDock);\n window.removeEventListener(\"popstate\", update);\n resizeObserver?.disconnect();\n ipcRenderer.removeListener(AI_READ_ACTIVITY_CHANNEL, onActivity);\n for (const requestId of activeRequests.current.keys()) {\n void ipcRenderer.invoke(AI_CANCEL_CHANNEL, requestId).catch(() => {});\n }\n activeRequests.current.clear();\n window.clearInterval(timer);\n observer.disconnect();\n window.removeEventListener(\"power-ai-open\", updateAndOpen);\n };\n }, []);\n useEffect(() => {\n setLauncherHidden(false);\n const onScroll = (event: Event) => {\n const target = event.target;\n if (!(target instanceof HTMLElement) || target.closest('.power-ai-panel, .Sidebar, [role=\"navigation\"], aside'))\n return;\n if (!target.closest('.ItemListLayout, .KubeObjectListLayout, main, [role=\"main\"]')) return;\n if (target.scrollHeight <= target.clientHeight || target.clientHeight <= 0) return;\n setLauncherHidden(target.scrollTop > 0 && target.scrollHeight - target.clientHeight - target.scrollTop <= 16);\n };\n document.addEventListener(\"scroll\", onScroll, true);\n return () => document.removeEventListener(\"scroll\", onScroll, true);\n }, [context.screen]);\n useEffect(() => {\n if (!open) return;\n const onEscape = (event: KeyboardEvent) => {\n if (event.key !== \"Escape\" || hasAiOverlay()) return;\n event.preventDefault();\n event.stopPropagation();\n event.stopImmediatePropagation();\n if (!dismissSuggestions.current()) setOpen(false);\n };\n window.addEventListener(\"keydown\", onEscape, true);\n return () => window.removeEventListener(\"keydown\", onEscape, true);\n }, [open]);\n useEffect(() => {\n if (!open || pinned) return;\n const onOutsideClick = (event: MouseEvent) => {\n const target = event.target;\n if (\n !(target instanceof Element) ||\n target.closest(\n \".power-ai-panel, .power-ai-launcher, .power-ai-overview-actions, [data-freelens-power-ai-overlay]\",\n )\n )\n return;\n setOpen(false);\n };\n document.addEventListener(\"click\", onOutsideClick, true);\n return () => document.removeEventListener(\"click\", onOutsideClick, true);\n }, [open, pinned]);\n useEffect(() => {\n const toggle = (event: KeyboardEvent) => {\n const mac = /Mac|iPhone|iPad/.test(navigator.platform);\n if (\n event.repeat ||\n event.isComposing ||\n event.keyCode === 229 ||\n event.altKey ||\n !event.shiftKey ||\n (mac ? !event.metaKey || event.ctrlKey : !event.ctrlKey || event.metaKey) ||\n event.code !== \"KeyY\" ||\n !preferences.enabled ||\n !isClusterDocument() ||\n hasAiOverlay()\n )\n return;\n event.preventDefault();\n event.stopPropagation();\n event.stopImmediatePropagation();\n setContext(readAiContext());\n setOpen((value) => !value);\n };\n window.addEventListener(\"keydown\", toggle, true);\n return () => window.removeEventListener(\"keydown\", toggle, true);\n }, [preferences, isClusterDocument]);\n const availablePanelWidth = Math.max(1, viewportWidth - Math.max(0, launcherLeft - 16));\n const panelWidth = clampAiPanelWidth(preferences.chatPanelWidth ?? DEFAULT_AI_PANEL_WIDTH, availablePanelWidth);\n const shortcutLabel = /Mac|iPhone|iPad/.test(navigator.platform) ? \"⌘⇧Y\" : \"Ctrl+Shift+Y\";\n const key = context.clusterId ?? \"global\";\n const messages = preferences.conversations[key] ?? [];\n const busy = pending.includes(key);\n const readActivity = activity.key === key ? activity.reads : [];\n useEffect(() => {\n const element = messagesElement.current;\n if (element && following.current) element.scrollTop = element.scrollHeight;\n }, [messages.length, busy, open, key]);\n useEffect(() => {\n following.current = true;\n const element = messagesElement.current;\n if (element && open) element.scrollTop = element.scrollHeight;\n }, [open, key]);\n if (!preferences.enabled || !isClusterDocument() || coveredByOverlay) return null;\n const send = async (starter?: string) => {\n const question = expandAiShortcut(\n (starter ?? draft).trim(),\n AiShortcutsStore.getInstanceOrCreate<AiShortcutsStore>().shortcuts,\n );\n if (!question || busy) return;\n if (question.length > 20_000) {\n setError(\"Message is too long. Please keep it under 20,000 characters.\");\n return;\n }\n const requestContext = attachedAiContext(readAiContext());\n if ((requestContext.clusterId ?? \"global\") !== key) {\n setContext(requestContext);\n return;\n }\n following.current = true;\n const next: AiMessage[] = [...messages, { role: \"user\", text: question }];\n preferences.setMessages(key, next);\n setDraft(\"\");\n setError(\"\");\n setStopped((keys) => keys.filter((entry) => entry !== key));\n setActivity({ key, reads: [] });\n setPending((keys) => [...keys, key]);\n const provider = preferences.provider;\n const requestId = crypto.randomUUID();\n activeRequests.current.set(requestId, key);\n try {\n const response = await ipcRenderer.invoke(AI_CHAT_CHANNEL, {\n requestId,\n messages: next.slice(-80).reduceRight<AiMessage[]>((tail, message) => {\n if (tail.reduce((length, item) => length + item.text.length, 0) + message.text.length < 100_000)\n tail.unshift({ role: message.role, text: message.text });\n return tail;\n }, []),\n context: requestContext,\n systemPrompt: [preferences.systemPrompt, requestContext.clusterId ? preferences.clusterPrompt : \"\"]\n .filter(Boolean)\n .join(\"\\n\\n\"),\n model: preferences.model,\n speed: preferences.speed,\n reasoningEffort: preferences.reasoningEffort,\n });\n if (activeRequests.current.get(requestId) !== key) return;\n if (!response || typeof response.text !== \"string\") throw new Error(\"Invalid response\");\n setActivity({\n key,\n reads: Array.isArray(response.reads)\n ? response.reads\n .filter(\n (read: AiReadActivity) =>\n [\"pods\", \"nodes\", \"resources\", \"logs\"].includes(read?.method) &&\n [\"ok\", \"unavailable\"].includes(read?.status),\n )\n .slice(0, 6)\n : [],\n });\n preferences.setMessages(key, [\n ...next,\n {\n role: \"assistant\",\n text: response.text,\n provider: response.provider === \"claude\" ? \"claude\" : provider,\n references: normalizeAiReferences(response.references),\n },\n ]);\n } catch (failure) {\n if (activeRequests.current.get(requestId) !== key) return;\n const code = String(failure).match(/FREELENS_AI_([A-Z_]+)/)?.[1];\n const messages: Record<string, string> = {\n READ_LIMIT: \"The assistant reached the read limit. Try a more specific question.\",\n TIMEOUT: \"The request timed out. Please try again.\",\n INVALID_REPLY: \"The assistant returned an incomplete reply. Please try again.\",\n CLI_FAILURE: \"The selected CLI request failed. Check your model access or try again.\",\n CANCELLED: \"The request was canceled.\",\n UNSAFE_POLICY:\n \"Claude managed policy cannot be safely isolated. Use Codex or ask your administrator to disable managed hooks and command helpers.\",\n INPUT_LIMIT: \"The request is too large. Start a new chat or shorten the message.\",\n };\n setError(\n (code && messages[code]) ||\n \"Unable to complete the request. Check that the selected CLI is installed and signed in, then try again.\",\n );\n } finally {\n activeRequests.current.delete(requestId);\n setPending((keys) => keys.filter((entry) => entry !== key));\n }\n };\n const stopResponse = () => {\n const requestId = [...activeRequests.current].find(([, requestKey]) => requestKey === key)?.[0];\n if (!requestId) return;\n activeRequests.current.delete(requestId);\n setStopped((keys) => [...keys.filter((entry) => entry !== key), key]);\n setActivity({ key, reads: [] });\n setError(\"\");\n void ipcRenderer.invoke(AI_CANCEL_CHANNEL, requestId).catch(() => {});\n };\n clusterReview.current = () => {\n const currentKey = readAiContext().clusterId;\n if (!currentKey || currentKey !== key || preferences.conversations[currentKey]?.length) return;\n void send(\n preferences.clusterPrompt.trim() ||\n \"Review this cluster using read-only queries and summarize its health and useful next steps.\",\n );\n };\n return (\n <>\n <style>{styles}</style>\n {!open && (\n <button\n type=\"button\"\n className={`power-ai-launcher${launcherHidden ? \" power-ai-launcher-hidden\" : \"\"}`}\n aria-hidden={launcherHidden || undefined}\n tabIndex={launcherHidden ? -1 : 0}\n style={{\n bottom: launcherBottom,\n left: resourceDetailsOpen ? launcherLeft : \"auto\",\n right: resourceDetailsOpen ? \"auto\" : 16,\n }}\n onClick={() => setOpen(true)}\n aria-label=\"Open AI assistant\"\n title={`Open AI assistant (${shortcutLabel})`}\n >\n <span aria-hidden=\"true\">\n <AiIcon material=\"chat_bubble_outline\" size={16} />\n </span>{\" \"}\n AI\n </button>\n )}\n {open && (\n <aside\n className=\"power-ai-panel\"\n aria-label=\"AI assistant\"\n style={{ \"--power-ai-font-size\": `${preferences.chatFontSize ?? 14}px`, width: panelWidth } as CSSProperties}\n >\n <AiResizeHandle\n width={panelWidth}\n available={availablePanelWidth}\n onChange={(width) => preferences.setChatPanelWidth(width)}\n />\n <header>\n <strong className=\"power-ai-title\">\n <span className=\"power-ai-brand\" title=\"AI assistant\">\n <AiIcon material=\"auto_awesome\" size={18} /> AI\n </span>{\" \"}\n Assistant\n </strong>\n <button\n type=\"button\"\n disabled={busy}\n aria-label=\"New chat\"\n title=\"Clear this conversation and start a new chat\"\n onClick={() => {\n preferences.setMessages(key, []);\n setStopped((keys) => keys.filter((entry) => entry !== key));\n setActivity({ key, reads: [] });\n setError(\"\");\n }}\n >\n <AiIcon material=\"add_comment\" size={16} /> New chat\n </button>\n <button\n type=\"button\"\n className=\"power-ai-pin\"\n aria-label=\"Pin AI assistant\"\n aria-pressed={pinned}\n title={pinned ? \"Unpin to close when clicking outside\" : \"Pin to keep the assistant open\"}\n onClick={() => setPinned((value) => !value)}\n >\n <AiIcon material=\"push_pin\" size={18} />\n </button>\n <button\n type=\"button\"\n onPointerDown={(event) => event.stopPropagation()}\n onMouseDown={(event) => event.stopPropagation()}\n onClick={(event) => {\n event.stopPropagation();\n setOpen(false);\n }}\n className=\"power-ai-close\"\n aria-label=\"Close AI assistant\"\n title=\"Close AI assistant\"\n >\n <span aria-hidden=\"true\">\n <AiIcon material=\"close\" size={18} />\n </span>\n </button>\n </header>\n <div className=\"power-ai-context\">\n {context.clusterId ? \"Cluster conversation\" : \"General conversation\"} · {context.screen}\n {context.resource && ` · ${context.resource.kind}/${context.resource.name}`}\n <br />\n Only screen and resource metadata are attached automatically.\n </div>\n <div\n className=\"power-ai-messages\"\n onScroll={(event) => {\n const element = event.currentTarget;\n following.current = element.scrollHeight - element.scrollTop - element.clientHeight < 48;\n }}\n aria-live=\"polite\"\n ref={messagesElement}\n >\n {messages.length === 0 && (\n <div className=\"power-ai-starters\">\n <p style={{ marginBottom: 12 }}>Ask about this screen or your cluster:</p>\n <AiStarterPrompts\n disabled={busy}\n onSelect={(prompt) => {\n void send(prompt);\n }}\n />\n </div>\n )}\n {messages.map((message, index) => (\n <div className={`power-ai-message power-ai-message-${message.role}`} key={index}>\n <strong>\n {message.role === \"user\" ? (\n <span title=\"You\">\n <AiIcon material=\"person_outline\" size={16} />\n </span>\n ) : (\n <AiProviderIcon provider={message.provider === \"claude\" ? \"claude\" : \"codex\"} />\n )}\n {message.role === \"user\" ? \"You\" : message.provider === \"claude\" ? \"Claude\" : \"Codex\"}\n {message.role === \"assistant\" && <AiCopyAnswer text={message.text} />}\n </strong>\n <AiMessageContent text={message.text} />\n {message.role === \"assistant\" && context.clusterId && (\n <AiResourceReferences\n clusterId={context.clusterId}\n references={message.references}\n text={message.text}\n onOpened={() => setOpen(false)}\n />\n )}\n </div>\n ))}\n {readActivity.length > 0 && (\n <div\n className=\"power-ai-read-activity\"\n style={{ fontSize: 11, color: \"var(--textColorSecondary)\", margin: \"8px 16px\" }}\n >\n {readActivity.map((read, index) => (\n <span\n key={index}\n title={`${read.method} · ${read.status === \"reading\" ? \"reading\" : read.status === \"ok\" ? \"read\" : \"unavailable\"}`}\n data-method={read.method}\n data-status={read.status}\n style={{ marginRight: 10 }}\n >\n <AiIcon\n material={\n read.status === \"reading\"\n ? \"sync\"\n : read.status === \"ok\"\n ? \"check_circle_outline\"\n : \"info_outline\"\n }\n size={13}\n />{\" \"}\n {read.method} ·{\" \"}\n {read.status === \"reading\" ? \"reading\" : read.status === \"ok\" ? \"read\" : \"unavailable\"}\n </span>\n ))}\n </div>\n )}\n {busy && (\n <p className=\"power-ai-thinking\" role=\"status\">\n {stopped.includes(key) ? \"Stopping response\" : \"Thinking\"}\n <span className=\"power-ai-dots\" aria-hidden=\"true\">\n <span>.</span>\n <span>.</span>\n <span>.</span>\n </span>\n </p>\n )}\n {!busy && stopped.includes(key) && (\n <p className=\"power-ai-cancellation\" role=\"status\">\n Response stopped{\" \"}\n <button\n type=\"button\"\n aria-label=\"Dismiss cancellation\"\n className=\"power-ai-dismiss\"\n title=\"Dismiss\"\n onClick={() => setStopped((keys) => keys.filter((entry) => entry !== key))}\n >\n <AiIcon material=\"close\" size={14} />\n </button>\n </p>\n )}\n {error && <p role=\"alert\">{error}</p>}\n </div>\n <form\n onSubmit={(event) => {\n event.preventDefault();\n void send();\n }}\n >\n {suggestions.length > 0 && (\n <div\n className=\"power-ai-autocomplete\"\n role=\"listbox\"\n id=\"power-ai-commands\"\n aria-label=\"Prompt shortcuts\"\n >\n {suggestions.map((shortcut, index) => (\n <button\n type=\"button\"\n role=\"option\"\n id={`power-ai-command-${index}`}\n aria-selected={index === suggestionIndex % suggestions.length}\n key={shortcut.id}\n title={`Insert /${shortcut.command}: ${shortcut.label}`}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => selectSuggestion(index)}\n >\n <span>/{shortcut.command}</span>\n <span>{shortcut.label}</span>\n </button>\n ))}\n </div>\n )}\n <AiContextPreview context={attachedAiContext(context)} />\n <textarea\n ref={composer}\n aria-controls={suggestions.length ? \"power-ai-commands\" : undefined}\n aria-expanded={suggestions.length > 0}\n aria-activedescendant={\n suggestions.length ? `power-ai-command-${suggestionIndex % suggestions.length}` : undefined\n }\n autoFocus\n aria-label=\"Message\"\n placeholder=\"Ask about this cluster…\"\n onKeyDown={(event) => {\n if (event.nativeEvent.isComposing || event.keyCode === 229) return;\n if (suggestions.length && !event.shiftKey) {\n if (event.key === \"ArrowDown\" || event.key === \"ArrowUp\") {\n event.preventDefault();\n setSuggestionIndex(\n (index) =>\n (index + (event.key === \"ArrowDown\" ? 1 : suggestions.length - 1)) % suggestions.length,\n );\n return;\n }\n if (event.key === \"Enter\" || event.key === \"Tab\") {\n event.preventDefault();\n selectSuggestion(suggestionIndex % suggestions.length);\n return;\n }\n }\n if (\n event.key === \"Enter\" &&\n !event.shiftKey &&\n !event.nativeEvent.isComposing &&\n event.keyCode !== 229\n ) {\n event.preventDefault();\n if (!busy) void send();\n }\n }}\n value={draft}\n onChange={(event) => {\n setDraft(event.target.value);\n setSuggestionIndex(0);\n setDismissedDraft(undefined);\n }}\n disabled={busy}\n />\n <div className=\"power-ai-composer-footer\">\n <span>Enter to send · Shift+Enter for newline</span>\n {busy ? (\n <button\n type=\"button\"\n aria-label=\"Stop response\"\n disabled={stopped.includes(key)}\n onClick={stopResponse}\n >\n <AiIcon material=\"stop\" size={16} /> Stop\n </button>\n ) : (\n <button type=\"submit\" disabled={!draft.trim()} aria-label=\"Send\">\n <AiIcon material=\"send\" size={16} />\n </button>\n )}\n </div>\n </form>\n </aside>\n )}\n </>\n );\n});\n\nexport function startAiChat(isClusterDocument: () => boolean = isAiClusterDocument): () => void {\n const container = document.createElement(\"div\");\n container.dataset.freelensPowerAi = \"\";\n document.body.append(container);\n let mounted = false;\n let overviewActions: HTMLDivElement | undefined;\n let overviewIcon: HTMLSpanElement | undefined;\n let overviewLabel: HTMLSpanElement | undefined;\n let overviewResize: ResizeObserver | undefined;\n const updateOverviewLabel = () => {\n const overview = overviewActions?.nextElementSibling;\n const compact = Boolean(overview?.querySelector(\"[data-freelens-power-monitoring]\") && overview.clientWidth > 960);\n const label = compact ? \"Ask AI\" : \"Ask about cluster\";\n if (overviewLabel && overviewLabel.textContent !== label) overviewLabel.textContent = label;\n overviewActions?.querySelector(\"button\")?.setAttribute(\"aria-label\", compact ? \"Ask AI about cluster\" : label);\n };\n const removeOverview = () => {\n overviewResize?.disconnect();\n overviewResize = undefined;\n if (overviewIcon) ReactDOM.unmountComponentAtNode(overviewIcon);\n overviewIcon = undefined;\n overviewLabel = undefined;\n overviewActions?.remove();\n overviewActions = undefined;\n };\n const preferences = AiPreferencesStore.getInstanceOrCreate<AiPreferencesStore>();\n const reconcile = () => {\n const overview =\n preferences.enabled &&\n isClusterDocument() &&\n Renderer.Catalog.activeCluster.get() &&\n document.querySelector('[data-testid=\"cluster-overview-page\"]');\n if (!overview) {\n removeOverview();\n return;\n }\n if (overviewActions?.isConnected && overviewActions.nextElementSibling === overview) {\n updateOverviewLabel();\n return;\n }\n removeOverview();\n overviewActions = document.createElement(\"div\");\n overviewActions.className = \"power-ai-overview-actions\";\n const overviewButton = document.createElement(\"button\");\n overviewButton.type = \"button\";\n overviewButton.setAttribute(\"aria-label\", \"Ask about cluster\");\n overviewButton.title = \"Open the AI assistant to ask about this cluster\";\n overviewIcon = document.createElement(\"span\");\n overviewIcon.setAttribute(\"aria-hidden\", \"true\");\n overviewLabel = document.createElement(\"span\");\n overviewButton.append(overviewIcon, overviewLabel);\n overviewButton.onclick = () => window.dispatchEvent(new Event(\"power-ai-open\"));\n overviewActions.append(overviewButton);\n overview.before(overviewActions);\n updateOverviewLabel();\n if (typeof ResizeObserver !== \"undefined\") {\n overviewResize = new ResizeObserver(updateOverviewLabel);\n overviewResize.observe(overview);\n }\n ReactDOM.render(<AiIcon material=\"auto_awesome\" size={16} />, overviewIcon);\n };\n const observer = new MutationObserver(reconcile);\n const stop = autorun(() => {\n if (preferences.enabled && !mounted) {\n observer.observe(document.body, { childList: true, subtree: true });\n mounted = true;\n ReactDOM.render(<AiChat isClusterDocument={isClusterDocument} />, container);\n } else if (!preferences.enabled && mounted) {\n observer.disconnect();\n ReactDOM.unmountComponentAtNode(container);\n mounted = false;\n }\n reconcile();\n });\n return () => {\n stop();\n observer.disconnect();\n removeOverview();\n ReactDOM.unmountComponentAtNode(container);\n container.remove();\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ai.js","names":[],"sources":["../../src/renderer/ai.tsx"],"sourcesContent":["import { Renderer } from \"@freelensapp/extensions\";\nimport { ipcRenderer } from \"electron\";\nimport { autorun } from \"mobx\";\nimport { observer } from \"mobx-react\";\nimport { type CSSProperties, useEffect, useRef, useState } from \"react\";\nimport ReactDOM from \"react-dom\";\nimport { AI_CHAT_CHANNEL, AI_READ_ACTIVITY_CHANNEL, type AiReadActivity } from \"../common/ai\";\nimport { AI_CANCEL_CHANNEL, attachedAiContext, normalizeAiReferences } from \"../common/ai-extras\";\nimport { expandAiShortcut } from \"../common/ai-shortcuts\";\nimport { type AiMessage, AiPreferencesStore } from \"../common/store/ai-preferences-store\";\nimport { AiShortcutsStore } from \"../common/store/ai-shortcuts-store\";\nimport { AiCopyAnswer } from \"./ai-copy-answer\";\nimport { AiContextPreview, AiResourceReferences } from \"./ai-extras\";\nimport { AiIcon } from \"./ai-icon\";\nimport { AiMessageContent } from \"./ai-message\";\nimport { AiProviderIcon } from \"./ai-provider-icon\";\nimport { AiResizeHandle, clampAiPanelWidth, DEFAULT_AI_PANEL_WIDTH } from \"./ai-resize\";\nimport { AiStarterPrompts } from \"./ai-shortcuts\";\nimport {\n type AiTerminalAttachment,\n AiTerminalContext,\n activeAiTerminal,\n captureAiTerminal,\n} from \"./ai-terminal-context\";\n\nexport interface AiScreenContext {\n clusterId?: string;\n screen?: string;\n resource?: { kind?: string; namespace?: string; name?: string };\n}\n\nexport function readAiContext(): AiScreenContext {\n const clusterId = Renderer.Catalog.activeCluster.get()?.metadata.uid;\n const screen = window.location.pathname;\n const details = new URLSearchParams(window.location.search).get(\"kube-details\");\n const match =\n details?.match(/^\\/api(?:\\/v\\d+)?\\/namespaces\\/([^/]+)\\/([^/]+)\\/([^/]+)$/) ??\n details?.match(/^\\/apis\\/[^/]+\\/[^/]+\\/namespaces\\/([^/]+)\\/([^/]+)\\/([^/]+)$/);\n const clusterResource =\n details?.match(/^\\/api\\/[^/]+\\/([^/]+)\\/([^/]+)$/) ?? details?.match(/^\\/apis\\/[^/]+\\/[^/]+\\/([^/]+)\\/([^/]+)$/);\n const resource = match\n ? { namespace: match[1], kind: match[2], name: match[3] }\n : clusterResource\n ? { kind: clusterResource[1], name: clusterResource[2] }\n : undefined;\n return { clusterId, screen, ...(resource ? { resource } : {}) };\n}\n\nexport function isAiClusterDocument(): boolean {\n return window.top !== window && Boolean(Renderer.Catalog.activeCluster.get());\n}\n\nexport function aiLauncherBottom(): number {\n const dock = document.querySelector<HTMLElement>(\".Dock\");\n if (!dock) return 16;\n const rect = dock.getBoundingClientRect();\n const style = window.getComputedStyle(dock);\n if (\n dock.hidden ||\n style.display === \"none\" ||\n style.visibility === \"hidden\" ||\n rect.width <= 0 ||\n rect.height <= 0 ||\n rect.top <= 0 ||\n rect.top >= window.innerHeight\n )\n return 16;\n return Math.max(16, window.innerHeight - rect.top + 16);\n}\n\nexport function aiLauncherLeft(): number {\n const sidebar = document.querySelector<HTMLElement>('[data-testid=\"cluster-sidebar\"], .Sidebar');\n const dock = document.querySelector<HTMLElement>(\".Dock\");\n let contentLeft = 0;\n for (const [element, edge] of [\n [sidebar, \"right\"],\n [dock, \"left\"],\n ] as const) {\n if (!element || element.hidden) continue;\n const style = window.getComputedStyle(element);\n const rect = element.getBoundingClientRect();\n if (style.display === \"none\" || style.visibility === \"hidden\" || rect.width <= 0) continue;\n const value = rect[edge];\n if (Number.isFinite(value) && value >= 0 && value < window.innerWidth - 80)\n contentLeft = Math.max(contentLeft, value);\n }\n return contentLeft + 16;\n}\n\nexport function hasAiResourceDetails(): boolean {\n if (new URLSearchParams(window.location.search).get(\"kube-details\")) return true;\n return Array.from(\n document.querySelectorAll<HTMLElement>(\".Drawer.KubeObjectDetails, .Drawer.ReleaseDetails, .DetailsDrawer\"),\n ).some((element) => {\n const style = window.getComputedStyle(element);\n const rect = element.getBoundingClientRect();\n return (\n !element.hidden && style.display !== \"none\" && style.visibility !== \"hidden\" && rect.width > 0 && rect.height > 0\n );\n });\n}\n\nexport function hasAiOverlay(): boolean {\n return Array.from(document.querySelectorAll<HTMLElement>('[role=\"dialog\"], dialog[open], .Dialog')).some(\n (element) => {\n const style = window.getComputedStyle(element);\n return !element.hidden && style.display !== \"none\" && style.visibility !== \"hidden\";\n },\n );\n}\n\nconst styles = `\n@keyframes power-ai-spin { to { transform: rotate(360deg); } }\n@keyframes power-ai-dot { 0%, 80%, 100% { opacity: .25; } 40% { opacity: 1; } }\nbody:has(.AddRemoveButtons .remove-button:not([data-freelens-power-read-only])) .power-ai-launcher { display: none; }\n.power-ai-read-activity > span { display: inline-flex; align-items: center; gap: 4px; }\n.power-ai-read-activity [data-status=\"reading\"] .Icon { animation: power-ai-spin 1.2s linear infinite; }\n.power-ai-thinking { margin: 12px 16px 18px; line-height: 1.5; color: var(--textColorSecondary); }\n.power-ai-dots > span { animation: power-ai-dot 1.3s ease-in-out infinite; }\n.power-ai-dots > span:nth-child(2) { animation-delay: .15s; }\n.power-ai-dots > span:nth-child(3) { animation-delay: .3s; }\n@media (prefers-reduced-motion: reduce) { .power-ai-read-activity [data-status=\"reading\"] .Icon, .power-ai-dots > span { animation: none; } }\n@keyframes power-ai-enter { from { transform: translateX(100%); } to { transform: translateX(0); } }\n:root .power-ai-launcher { position: fixed; bottom: 16px; left: auto; right: 16px; z-index: 100; display: inline-flex; align-items: center; gap: 6px; min-width: 0; min-height: 0; height: 34px; border: 1px solid var(--primary, #5896ff); border-radius: 24px; padding: 0 13px; background: var(--contentColor, #242424); color: var(--textColorAccent); box-shadow: 0 3px 12px #0003; font: inherit; font-size: 12px; font-weight: 500; line-height: 1; cursor: pointer; transition: opacity 180ms ease, background-color 140ms ease, box-shadow 140ms ease, transform 180ms ease; }\n.power-ai-overview-actions { position: relative; z-index: 5; height: 0; min-height: 0; flex: 0 0 0; pointer-events: none; }\n.power-ai-overview-actions + [data-testid=\"cluster-overview-page\"] [data-monitoring-summaries] { --power-monitoring-summary-top: 56px; }\n.power-ai-overview-actions button { transition: background-color 160ms ease, border-color 160ms ease, color 160ms ease, box-shadow 160ms ease; position: absolute; top: 12px; right: 12px; pointer-events: auto; box-shadow: 0 2px 8px #0002; display: inline-flex; flex: 0 0 auto; width: auto; align-items: center; gap: 6px; min-height: 32px; padding: 6px 12px; font: inherit; font-size: 12px; border: 1px solid var(--borderFaintColor); border-radius: 10px; color: var(--textColorPrimary); background: var(--contentColor); cursor: pointer; }\n.power-ai-overview-actions button:hover { border-color: var(--primary); color: var(--textColorAccent); background: var(--contentColor); }\n.power-ai-overview-actions button:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }\n.power-ai-launcher.power-ai-launcher-hidden { opacity: 0; transform: translateY(8px); pointer-events: none; }\n.power-ai-launcher .Icon { color: inherit; }\n.power-ai-launcher:hover { background: color-mix(in srgb, var(--primary, #5896ff) 12%, var(--contentColor, #242424)); box-shadow: 0 4px 12px #0003; transform: translateY(-1px); }\n.power-ai-launcher:active { transform: translateY(0); box-shadow: 0 2px 6px #0002; }\n@media (prefers-reduced-motion: reduce) { :root .power-ai-launcher { transition: none; } .power-ai-launcher:hover, .power-ai-launcher:active { transform: none; } }\n.power-ai-launcher:focus-visible { outline: 2px solid var(--primary, #5896ff); outline-offset: 3px; }\n.power-ai-panel { position: fixed; right: 0; top: 0; bottom: 0; width: min(560px, 100vw); z-index: 10001; display: flex; flex-direction: column; background: var(--contentColor, #242424); color: var(--textColorAccent, white); animation: power-ai-enter 160ms ease-out; border-left: 1px solid var(--borderFaintColor); box-shadow: -4px 0 24px #0004; }\n.power-ai-resize-handle { position: absolute; left: -4px; top: 0; bottom: 0; width: 8px; z-index: 2; cursor: col-resize; touch-action: none; }\n.power-ai-resize-handle:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }\n.power-ai-panel header { padding: 16px; display: flex; gap: 10px; flex-shrink: 0; }\n.power-ai-panel header { border-bottom: 1px solid var(--borderFaintColor); justify-content: space-between; align-items: center; }\n.power-ai-messages { overflow: auto; flex: 1; min-height: 0; padding: 24px 16px; font-size: var(--power-ai-font-size, 14px); line-height: 1.65; overscroll-behavior: contain; }\n.power-ai-message { overflow-wrap: anywhere; padding: 14px 16px; margin-bottom: 20px; color: var(--textColorAccent); border: 1px solid var(--borderFaintColor); border-radius: 8px; }\n.power-ai-panel button { padding: 7px 10px; border: 1px solid var(--borderFaintColor); border-radius: 8px; background: var(--contentColor); color: var(--textColorPrimary); cursor: pointer; }\n:root .power-ai-panel header button:is(.power-ai-close, .power-ai-pin) { width: 30px; height: 30px; padding: 0; display: inline-flex; align-items: center; justify-content: center; border: 0; border-radius: 6px; background: transparent; color: var(--textColorSecondary); }\n:root .power-ai-panel header button:is(.power-ai-close, .power-ai-pin):not(:disabled):not(.disabled):hover { color: var(--primary); background: color-mix(in srgb, var(--primary) 10%, transparent); }\n:root .power-ai-panel header button:is(.power-ai-close, .power-ai-pin):focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }\n:root .power-ai-panel button.power-ai-copy-answer { width: 24px; height: 24px; padding: 0; margin-left: auto; flex-shrink: 0; justify-content: center; border: 0; background: transparent; color: var(--textColorSecondary); }\n:root .power-ai-panel button.power-ai-copy-answer:not(:disabled):not(.disabled):hover { color: var(--primary); background: color-mix(in srgb, var(--primary) 10%, transparent); }\n:root .power-ai-panel button.power-ai-copy-answer:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }\n.power-ai-cancellation { display: flex; align-items: center; gap: 6px; }\n:root .power-ai-panel button.power-ai-dismiss { width: 24px; height: 24px; padding: 0; justify-content: center; border: 0; border-radius: 6px; background: transparent; color: var(--textColorSecondary); }\n:root .power-ai-panel button.power-ai-dismiss:hover { color: var(--primary); background: color-mix(in srgb, var(--primary) 10%, transparent); }\n:root .power-ai-panel button.power-ai-dismiss:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }\n.power-ai-panel button:disabled { opacity: 0.5; cursor: default; }\n .power-ai-panel textarea { display: block; width: 100%; box-sizing: border-box; min-width: 0; min-height: 64px; max-height: 180px; field-sizing: content; padding: 12px 16px 6px; border: 0; border-radius: 12px; background: transparent; color: var(--textColorAccent); font: inherit; font-size: var(--power-ai-font-size, 14px); line-height: 1.5; resize: none; }\n.power-ai-panel textarea::placeholder { color: var(--textColorSecondary); opacity: 1; }\n.power-ai-panel textarea:focus { outline: none; }\n.power-ai-composer-footer { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 4px 10px 10px 16px; }\n.power-ai-composer-footer > span { color: var(--textColorSecondary); font-size: 11px; line-height: 1.5; }\n:root .power-ai-panel form button[type=\"submit\"] { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 34px; width: 34px; height: 34px; padding: 0; border-radius: 10px; }\n:root .power-ai-panel form button[type=\"submit\"]:not(:disabled):not(.disabled) { background-color: var(--primary); border-color: var(--primary); color: white; }\n:root .power-ai-panel form button[type=\"submit\"]:not(:disabled):not(.disabled):hover { background-color: color-mix(in srgb, var(--primary) 88%, white 12%); border-color: color-mix(in srgb, var(--primary) 88%, white 12%); color: white; }\n:root .power-ai-panel form button[type=\"submit\"]:focus-visible { outline: 2px solid var(--primary); outline-offset: 3px; }\n:root .power-ai-panel form button[type=\"submit\"]:disabled { background-color: var(--contentColor); border-color: var(--borderFaintColor); color: var(--textColorSecondary); }\n.power-ai-message-user { border-color: color-mix(in srgb, var(--primary) 28%, var(--borderFaintColor)); background: color-mix(in srgb, var(--primary) 7%, var(--mainBackground)); }\n.power-ai-context { padding: 10px 20px; line-height: 1.5; border-bottom: 1px solid var(--borderFaintColor); font-size: 12px; color: var(--textColorSecondary); overflow-wrap: anywhere; }\n.power-ai-title, .power-ai-panel button { display: inline-flex; align-items: center; gap: 6px; }\n.power-ai-title { margin-right: auto; white-space: nowrap; color: var(--textColorAccent); }\n.power-ai-brand { display: inline-flex; align-items: center; gap: 6px; color: var(--primary); }\n.power-ai-brand .Icon { color: inherit; }\n:root .power-ai-panel header button.power-ai-pin[aria-pressed=\"true\"] { color: var(--primary); }\n.power-ai-panel header > button { flex-shrink: 0; }\n.power-ai-panel form { position: relative; flex-shrink: 0; margin: 0 16px 16px; border: 1px solid var(--borderFaintColor); border-radius: 12px; background: var(--mainBackground); transition: border-color 160ms ease; }\n.power-ai-panel form > .power-ai-context-preview { padding: 8px 48px 4px 16px !important; min-height: 34px; margin: 0; box-sizing: border-box; }\n.power-ai-panel form:focus-within { border-color: var(--primary); }\n.power-ai-message > strong { display: flex; align-items: center; gap: 8px; font-size: 12px; font-weight: 500; color: var(--textColorSecondary); margin-bottom: 10px; }\n.power-ai-message-assistant { border-color: transparent; background: transparent; }\n.power-ai-markdown { line-height: 1.65; font-size: var(--power-ai-font-size, 14px); color: var(--textColorAccent); }\n.power-ai-markdown p { margin: 0 0 14px; white-space: pre-wrap; }\n.power-ai-markdown p:last-child { margin-bottom: 0; }\n.power-ai-markdown ul, .power-ai-markdown ol { padding-left: 24px; margin: 10px 0 16px; }\n.power-ai-markdown ul { list-style: disc; }\n.power-ai-markdown ol { list-style: decimal; }\n.power-ai-markdown li { margin: 5px 0; }\n.power-ai-markdown li > ul, .power-ai-markdown li > ol { margin: 6px 0; }\n.power-ai-markdown li > p { margin-bottom: 6px; }\n.power-ai-markdown :is(h1, h2, h3, h4, h5, h6) { color: var(--textColorAccent); font-weight: 600; line-height: 1.4; margin: 24px 0 12px; }\n.power-ai-markdown :is(h1, h2, h3, h4, h5, h6):first-child { margin-top: 0; }\n.power-ai-markdown h1 { font-size: 1.43em; }\n.power-ai-markdown h2 { font-size: 1.29em; }\n.power-ai-markdown h3 { font-size: 1.14em; }\n.power-ai-markdown :is(h4, h5, h6) { font-size: 1em; }\n.power-ai-markdown blockquote { margin: 16px 0; padding: 4px 14px; border-left: 3px solid var(--borderColor); color: var(--textColorSecondary); }\n.power-ai-markdown blockquote > p:last-child { margin-bottom: 0; }\n.power-ai-markdown table { display: block; max-width: 100%; overflow-x: auto; margin: 16px 0; border-collapse: collapse; font-size: max(10px, calc(var(--power-ai-font-size, 14px) - 1px)); }\n.power-ai-markdown th, .power-ai-markdown td { padding: 9px 12px; border: 1px solid var(--borderFaintColor); text-align: left; }\n.power-ai-markdown th { font-weight: 600; background: color-mix(in srgb, var(--textColorAccent) 5%, transparent); }\n.power-ai-markdown a { color: var(--primary); text-decoration: underline; text-underline-offset: 2px; }\n.power-ai-markdown hr { margin: 20px 0; border: 0; border-top: 1px solid var(--borderFaintColor); }\n.power-ai-markdown code { font-family: var(--font-monospace, monospace); font-size: max(10px, calc(var(--power-ai-font-size, 14px) - 1px)); background: color-mix(in srgb, var(--textColorAccent) 8%, transparent); padding: 1px 4px; border-radius: 4px; }\n.power-ai-code { margin: 12px 0; border: 1px solid var(--borderFaintColor); border-radius: 8px; overflow: hidden; background: var(--mainBackground); }\n.power-ai-code-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 6px 8px; border-bottom: 1px solid var(--borderFaintColor); color: var(--textColorSecondary); font-size: 11px; }\n.power-ai-code-toolbar > div { display: flex; gap: 4px; }\n.power-ai-code-toolbar button { padding: 4px 6px; font-size: 11px; }\n.power-ai-code pre { margin: 0; padding: 12px; overflow-x: auto; white-space: pre; }\n.power-ai-code pre code { padding: 0; background: transparent; }\n.power-ai-code-hint, .power-ai-code-feedback:not(:empty) { padding: 0 12px 10px; color: var(--textColorSecondary); font-size: 11px; }\n.power-ai-autocomplete { position: absolute; bottom: calc(100% + 8px); left: 0; right: 0; max-height: 240px; overflow-y: auto; padding: 6px; border: 1px solid var(--borderColor); border-radius: 10px; background: var(--contentColor); box-shadow: 0 4px 16px #0003; }\n.power-ai-autocomplete button { display: flex; width: 100%; justify-content: space-between; gap: 12px; border: 0; text-align: left; }\n.power-ai-autocomplete button[aria-selected=\"true\"] { background: color-mix(in srgb, var(--primary) 14%, var(--contentColor)); color: var(--textColorAccent); }\n.power-ai-autocomplete button > span:last-child { color: var(--textColorSecondary); font-size: 12px; }\n@media (prefers-reduced-motion: reduce) { .power-ai-panel { animation: none; } }\n`;\n\nconst AiChat = observer(({ isClusterDocument }: { isClusterDocument: () => boolean }) => {\n const preferences = AiPreferencesStore.getInstanceOrCreate<AiPreferencesStore>();\n const [open, setOpen] = useState(false);\n const [pinned, setPinned] = useState(false);\n const [launcherBottom, setLauncherBottom] = useState(aiLauncherBottom);\n const [launcherLeft, setLauncherLeft] = useState(aiLauncherLeft);\n const [resourceDetailsOpen, setResourceDetailsOpen] = useState(hasAiResourceDetails);\n const [viewportWidth, setViewportWidth] = useState(window.innerWidth);\n const [launcherHidden, setLauncherHidden] = useState(false);\n const [draft, setDraft] = useState(\"\");\n const [terminalAttachment, setTerminalAttachment] = useState<AiTerminalAttachment>();\n const [suggestionIndex, setSuggestionIndex] = useState(0);\n const [dismissedDraft, setDismissedDraft] = useState<string>();\n const suggestions =\n /^\\/[^\\s]*$/.test(draft) && dismissedDraft !== draft\n ? AiShortcutsStore.getInstanceOrCreate<AiShortcutsStore>().shortcuts.filter((shortcut) =>\n `${shortcut.command} ${shortcut.label}`.toLowerCase().includes(draft.slice(1).toLowerCase()),\n )\n : [];\n const dismissSuggestions = useRef<() => boolean>(() => false);\n dismissSuggestions.current = () => {\n if (!suggestions.length) return false;\n setDismissedDraft(draft);\n return true;\n };\n const following = useRef(true);\n const composer = useRef<HTMLTextAreaElement>(null);\n const selectSuggestion = (index: number) => {\n const shortcut = suggestions[index];\n if (!shortcut) return;\n setDraft(`/${shortcut.command} `);\n setSuggestionIndex(0);\n composer.current?.focus();\n };\n const [context, setContext] = useState(readAiContext);\n const [pending, setPending] = useState<string[]>([]);\n const [error, setError] = useState(\"\");\n const [stopped, setStopped] = useState<string[]>([]);\n const activeRequests = useRef(new Map<string, string>());\n const [activity, setActivity] = useState<{\n key: string;\n reads: { method: AiReadActivity[\"method\"]; status: \"reading\" | \"ok\" | \"unavailable\" }[];\n }>({ key: \"\", reads: [] });\n const clusterReview = useRef<() => void>(() => {});\n const messagesElement = useRef<HTMLDivElement>(null);\n const [coveredByOverlay, setCoveredByOverlay] = useState(hasAiOverlay);\n useEffect(() => {\n let observedElements: Element[] = [];\n const resizeObserver =\n typeof ResizeObserver === \"undefined\"\n ? undefined\n : new ResizeObserver(() => {\n setLauncherBottom(aiLauncherBottom());\n setLauncherLeft(aiLauncherLeft());\n });\n const updateDock = () => {\n setViewportWidth(window.innerWidth);\n setLauncherBottom(aiLauncherBottom());\n setLauncherLeft(aiLauncherLeft());\n const elements = [\n document.querySelector(\".Dock\"),\n document.querySelector('[data-testid=\"cluster-sidebar\"], .Sidebar'),\n ].filter((element): element is Element => !!element);\n if (\n elements.length !== observedElements.length ||\n elements.some((element, index) => element !== observedElements[index])\n ) {\n resizeObserver?.disconnect();\n observedElements = elements;\n for (const element of elements) resizeObserver?.observe(element);\n }\n };\n const update = () => {\n updateDock();\n setContext(readAiContext());\n setResourceDetailsOpen(hasAiResourceDetails());\n setCoveredByOverlay(hasAiOverlay());\n };\n const onActivity = (_event: unknown, value: unknown) => {\n if (!value || typeof value !== \"object\") return;\n const entry = value as { requestId?: string; method?: string; status?: string };\n const requestKey = activeRequests.current.get(entry.requestId ?? \"\");\n if (\n !requestKey ||\n requestKey !== readAiContext().clusterId ||\n ![\"pods\", \"nodes\", \"resources\", \"logs\"].includes(entry.method ?? \"\") ||\n ![\"reading\", \"ok\", \"unavailable\"].includes(entry.status ?? \"\")\n )\n return;\n const read = {\n method: entry.method as AiReadActivity[\"method\"],\n status: entry.status as \"reading\" | \"ok\" | \"unavailable\",\n };\n setActivity((previous) => ({\n key: requestKey,\n reads: [\n ...(previous.key === requestKey ? previous.reads.filter((item) => item.method !== read.method) : []),\n read,\n ],\n }));\n };\n ipcRenderer.on(AI_READ_ACTIVITY_CHANNEL, onActivity);\n window.addEventListener(\"resize\", updateDock);\n window.addEventListener(\"popstate\", update);\n update();\n const timer = window.setInterval(update, 500);\n const observer = new MutationObserver(update);\n observer.observe(document.body, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: [\"class\", \"style\", \"hidden\", \"open\"],\n });\n window.addEventListener(\"power-ai-open\", updateAndOpen);\n function updateAndOpen() {\n update();\n setOpen(true);\n clusterReview.current();\n }\n return () => {\n window.removeEventListener(\"resize\", updateDock);\n window.removeEventListener(\"popstate\", update);\n resizeObserver?.disconnect();\n ipcRenderer.removeListener(AI_READ_ACTIVITY_CHANNEL, onActivity);\n for (const requestId of activeRequests.current.keys()) {\n void ipcRenderer.invoke(AI_CANCEL_CHANNEL, requestId).catch(() => {});\n }\n activeRequests.current.clear();\n window.clearInterval(timer);\n observer.disconnect();\n window.removeEventListener(\"power-ai-open\", updateAndOpen);\n };\n }, []);\n useEffect(() => {\n setLauncherHidden(false);\n const onScroll = (event: Event) => {\n const target = event.target;\n if (!(target instanceof HTMLElement) || target.closest('.power-ai-panel, .Sidebar, [role=\"navigation\"], aside'))\n return;\n if (!target.closest('.ItemListLayout, .KubeObjectListLayout, main, [role=\"main\"]')) return;\n if (target.scrollHeight <= target.clientHeight || target.clientHeight <= 0) return;\n setLauncherHidden(target.scrollTop > 0 && target.scrollHeight - target.clientHeight - target.scrollTop <= 16);\n };\n document.addEventListener(\"scroll\", onScroll, true);\n return () => document.removeEventListener(\"scroll\", onScroll, true);\n }, [context.screen]);\n useEffect(() => {\n if (!open) return;\n const onEscape = (event: KeyboardEvent) => {\n if (event.key !== \"Escape\" || hasAiOverlay()) return;\n event.preventDefault();\n event.stopPropagation();\n event.stopImmediatePropagation();\n if (!dismissSuggestions.current()) setOpen(false);\n };\n window.addEventListener(\"keydown\", onEscape, true);\n return () => window.removeEventListener(\"keydown\", onEscape, true);\n }, [open]);\n useEffect(() => {\n if (!open || pinned) return;\n const onOutsideClick = (event: MouseEvent) => {\n const target = event.target;\n if (\n !(target instanceof Element) ||\n target.closest(\n \".power-ai-panel, .power-ai-launcher, .power-ai-overview-actions, [data-freelens-power-ai-overlay]\",\n )\n )\n return;\n setOpen(false);\n };\n document.addEventListener(\"click\", onOutsideClick, true);\n return () => document.removeEventListener(\"click\", onOutsideClick, true);\n }, [open, pinned]);\n useEffect(() => {\n const heldKeys = new Set<string>();\n let shiftDownAt: number | undefined;\n let lastTapAt: number | undefined;\n const reset = () => {\n shiftDownAt = undefined;\n lastTapAt = undefined;\n };\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key !== \"Shift\") heldKeys.add(event.code || event.key);\n if (\n event.key !== \"Shift\" ||\n event.repeat ||\n event.isComposing ||\n event.keyCode === 229 ||\n event.altKey ||\n event.ctrlKey ||\n event.metaKey ||\n heldKeys.size > 0 ||\n shiftDownAt !== undefined\n ) {\n reset();\n return;\n }\n shiftDownAt = performance.now();\n };\n const onKeyUp = (event: KeyboardEvent) => {\n if (event.key === \"Meta\") {\n // macOS can omit keyup events for keys released while [Meta] is held\n heldKeys.clear();\n reset();\n return;\n }\n heldKeys.delete(event.code || event.key);\n const now = performance.now();\n if (\n event.key !== \"Shift\" ||\n shiftDownAt === undefined ||\n now - shiftDownAt > 400 ||\n event.isComposing ||\n event.altKey ||\n event.ctrlKey ||\n event.metaKey ||\n !preferences.enabled ||\n !isClusterDocument() ||\n hasAiOverlay()\n ) {\n reset();\n return;\n }\n shiftDownAt = undefined;\n if (lastTapAt === undefined || now - lastTapAt > 400) {\n lastTapAt = now;\n return;\n }\n reset();\n setContext(readAiContext());\n setOpen((value) => !value);\n };\n window.addEventListener(\"keydown\", onKeyDown, true);\n window.addEventListener(\"keyup\", onKeyUp, true);\n const onBlur = () => {\n heldKeys.clear();\n reset();\n };\n window.addEventListener(\"blur\", onBlur);\n return () => {\n window.removeEventListener(\"keydown\", onKeyDown, true);\n window.removeEventListener(\"keyup\", onKeyUp, true);\n window.removeEventListener(\"blur\", onBlur);\n };\n }, [preferences, isClusterDocument]);\n const availablePanelWidth = Math.max(1, viewportWidth - Math.max(0, launcherLeft - 16));\n const panelWidth = clampAiPanelWidth(preferences.chatPanelWidth ?? DEFAULT_AI_PANEL_WIDTH, availablePanelWidth);\n const shortcutLabel = \"Shift, Shift\";\n const key = context.clusterId ?? \"global\";\n const messages = preferences.conversations[key] ?? [];\n const busy = pending.includes(key);\n const readActivity = activity.key === key ? activity.reads : [];\n useEffect(() => {\n const element = messagesElement.current;\n if (element && following.current) element.scrollTop = element.scrollHeight;\n }, [messages.length, busy, open, key]);\n useEffect(() => {\n following.current = true;\n const element = messagesElement.current;\n if (element && open) element.scrollTop = element.scrollHeight;\n }, [open, key]);\n useEffect(() => {\n if (!terminalAttachment) return;\n const update = () => {\n if (activeAiTerminal(terminalAttachment.clusterId) !== terminalAttachment.terminalId)\n setTerminalAttachment(undefined);\n };\n update();\n const timer = window.setInterval(update, 500);\n const observer = new MutationObserver(update);\n observer.observe(document.body, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: [\"class\", \"style\", \"hidden\", \"aria-hidden\", \"data-testid\"],\n });\n return () => {\n window.clearInterval(timer);\n observer.disconnect();\n };\n }, [terminalAttachment, context.clusterId]);\n if (!preferences.enabled || !isClusterDocument() || coveredByOverlay) return null;\n const send = async (starter?: string) => {\n const question = expandAiShortcut(\n (starter ?? draft).trim(),\n AiShortcutsStore.getInstanceOrCreate<AiShortcutsStore>().shortcuts,\n );\n if (!question || busy) return;\n if (question.length > 20_000) {\n setError(\"Message is too long. Please keep it under 20,000 characters.\");\n return;\n }\n const requestContext = attachedAiContext(readAiContext());\n if ((requestContext.clusterId ?? \"global\") !== key) {\n setContext(requestContext);\n return;\n }\n const terminalSnapshot =\n terminalAttachment?.clusterId === requestContext.clusterId\n ? captureAiTerminal(requestContext.clusterId, terminalAttachment?.terminalId)\n : undefined;\n if (terminalAttachment && !terminalSnapshot) {\n setTerminalAttachment(undefined);\n setError(\"The attached terminal changed or is unavailable. Attach it again before sending.\");\n return;\n }\n setTerminalAttachment(undefined);\n following.current = true;\n const next: AiMessage[] = [...messages, { role: \"user\", text: question }];\n preferences.setMessages(key, next);\n setDraft(\"\");\n setError(\"\");\n setStopped((keys) => keys.filter((entry) => entry !== key));\n setActivity({ key, reads: [] });\n setPending((keys) => [...keys, key]);\n const provider = preferences.provider;\n const requestId = crypto.randomUUID();\n activeRequests.current.set(requestId, key);\n try {\n const response = await ipcRenderer.invoke(AI_CHAT_CHANNEL, {\n requestId,\n messages: next.slice(-80).reduceRight<AiMessage[]>((tail, message) => {\n if (tail.reduce((length, item) => length + item.text.length, 0) + message.text.length < 100_000)\n tail.unshift({ role: message.role, text: message.text });\n return tail;\n }, []),\n context: requestContext,\n ...(terminalSnapshot ? { terminalSnapshot } : {}),\n systemPrompt: [preferences.systemPrompt, requestContext.clusterId ? preferences.clusterPrompt : \"\"]\n .filter(Boolean)\n .join(\"\\n\\n\"),\n model: preferences.model,\n speed: preferences.speed,\n reasoningEffort: preferences.reasoningEffort,\n });\n if (activeRequests.current.get(requestId) !== key) return;\n if (!response || typeof response.text !== \"string\") throw new Error(\"Invalid response\");\n setActivity({\n key,\n reads: Array.isArray(response.reads)\n ? response.reads\n .filter(\n (read: AiReadActivity) =>\n [\"pods\", \"nodes\", \"resources\", \"logs\"].includes(read?.method) &&\n [\"ok\", \"unavailable\"].includes(read?.status),\n )\n .slice(0, 6)\n : [],\n });\n preferences.setMessages(key, [\n ...next,\n {\n role: \"assistant\",\n text: response.text,\n provider: response.provider === \"claude\" ? \"claude\" : provider,\n references: normalizeAiReferences(response.references),\n },\n ]);\n } catch (failure) {\n if (activeRequests.current.get(requestId) !== key) return;\n const code = String(failure).match(/FREELENS_AI_([A-Z_]+)/)?.[1];\n const messages: Record<string, string> = {\n READ_LIMIT: \"The assistant reached the read limit. Try a more specific question.\",\n TIMEOUT: \"The request timed out. Please try again.\",\n INVALID_REPLY: \"The assistant returned an incomplete reply. Please try again.\",\n CLI_FAILURE: \"The selected CLI request failed. Check your model access or try again.\",\n CANCELLED: \"The request was canceled.\",\n UNSAFE_POLICY:\n \"Claude managed policy cannot be safely isolated. Use Codex or ask your administrator to disable managed hooks and command helpers.\",\n INPUT_LIMIT: \"The request is too large. Start a new chat or shorten the message.\",\n };\n setError(\n (code && messages[code]) ||\n \"Unable to complete the request. Check that the selected CLI is installed and signed in, then try again.\",\n );\n } finally {\n activeRequests.current.delete(requestId);\n setPending((keys) => keys.filter((entry) => entry !== key));\n }\n };\n const stopResponse = () => {\n const requestId = [...activeRequests.current].find(([, requestKey]) => requestKey === key)?.[0];\n if (!requestId) return;\n activeRequests.current.delete(requestId);\n setStopped((keys) => [...keys.filter((entry) => entry !== key), key]);\n setActivity({ key, reads: [] });\n setError(\"\");\n void ipcRenderer.invoke(AI_CANCEL_CHANNEL, requestId).catch(() => {});\n };\n clusterReview.current = () => {\n const currentKey = readAiContext().clusterId;\n if (!currentKey || currentKey !== key || preferences.conversations[currentKey]?.length) return;\n void send(\n preferences.clusterPrompt.trim() ||\n \"Review this cluster using read-only queries and summarize its health and useful next steps.\",\n );\n };\n return (\n <>\n <style>{styles}</style>\n {!open && (\n <button\n type=\"button\"\n className={`power-ai-launcher${launcherHidden ? \" power-ai-launcher-hidden\" : \"\"}`}\n aria-hidden={launcherHidden || undefined}\n tabIndex={launcherHidden ? -1 : 0}\n style={{\n bottom: launcherBottom,\n left: resourceDetailsOpen ? launcherLeft : \"auto\",\n right: resourceDetailsOpen ? \"auto\" : 16,\n }}\n onClick={() => setOpen(true)}\n aria-label=\"Open AI assistant\"\n title={`Open AI assistant (${shortcutLabel})`}\n >\n <span aria-hidden=\"true\">\n <AiIcon material=\"chat_bubble_outline\" size={16} />\n </span>{\" \"}\n AI\n </button>\n )}\n {open && (\n <aside\n className=\"power-ai-panel\"\n aria-label=\"AI assistant\"\n style={{ \"--power-ai-font-size\": `${preferences.chatFontSize ?? 14}px`, width: panelWidth } as CSSProperties}\n >\n <AiResizeHandle\n width={panelWidth}\n available={availablePanelWidth}\n onChange={(width) => preferences.setChatPanelWidth(width)}\n />\n <header>\n <strong className=\"power-ai-title\">\n <span className=\"power-ai-brand\" title=\"AI assistant\">\n <AiIcon material=\"auto_awesome\" size={18} /> AI\n </span>{\" \"}\n Assistant\n </strong>\n <button\n type=\"button\"\n disabled={busy}\n aria-label=\"New chat\"\n title=\"Clear this conversation and start a new chat\"\n onClick={() => {\n setTerminalAttachment(undefined);\n preferences.setMessages(key, []);\n setStopped((keys) => keys.filter((entry) => entry !== key));\n setActivity({ key, reads: [] });\n setError(\"\");\n }}\n >\n <AiIcon material=\"add_comment\" size={16} /> New chat\n </button>\n <button\n type=\"button\"\n className=\"power-ai-pin\"\n aria-label=\"Pin AI assistant\"\n aria-pressed={pinned}\n title={pinned ? \"Unpin to close when clicking outside\" : \"Pin to keep the assistant open\"}\n onClick={() => setPinned((value) => !value)}\n >\n <AiIcon material=\"push_pin\" size={18} />\n </button>\n <button\n type=\"button\"\n onPointerDown={(event) => event.stopPropagation()}\n onMouseDown={(event) => event.stopPropagation()}\n onClick={(event) => {\n event.stopPropagation();\n setOpen(false);\n }}\n className=\"power-ai-close\"\n aria-label=\"Close AI assistant\"\n title=\"Close AI assistant\"\n >\n <span aria-hidden=\"true\">\n <AiIcon material=\"close\" size={18} />\n </span>\n </button>\n </header>\n <div className=\"power-ai-context\">\n {context.clusterId ? \"Cluster conversation\" : \"General conversation\"} · {context.screen}\n {context.resource && ` · ${context.resource.kind}/${context.resource.name}`}\n <br />\n Only screen and resource metadata are attached automatically.\n </div>\n <div\n className=\"power-ai-messages\"\n onScroll={(event) => {\n const element = event.currentTarget;\n following.current = element.scrollHeight - element.scrollTop - element.clientHeight < 48;\n }}\n aria-live=\"polite\"\n ref={messagesElement}\n >\n {messages.length === 0 && (\n <div className=\"power-ai-starters\">\n <p style={{ marginBottom: 12 }}>Ask about this screen or your cluster:</p>\n <AiStarterPrompts\n disabled={busy}\n onSelect={(prompt) => {\n void send(prompt);\n }}\n />\n </div>\n )}\n {messages.map((message, index) => (\n <div className={`power-ai-message power-ai-message-${message.role}`} key={index}>\n <strong>\n {message.role === \"user\" ? (\n <span title=\"You\">\n <AiIcon material=\"person_outline\" size={16} />\n </span>\n ) : (\n <AiProviderIcon provider={message.provider === \"claude\" ? \"claude\" : \"codex\"} />\n )}\n {message.role === \"user\" ? \"You\" : message.provider === \"claude\" ? \"Claude\" : \"Codex\"}\n {message.role === \"assistant\" && <AiCopyAnswer text={message.text} />}\n </strong>\n <AiMessageContent text={message.text} />\n {message.role === \"assistant\" && context.clusterId && (\n <AiResourceReferences\n clusterId={context.clusterId}\n references={message.references}\n text={message.text}\n onOpened={() => setOpen(false)}\n />\n )}\n </div>\n ))}\n {readActivity.length > 0 && (\n <div\n className=\"power-ai-read-activity\"\n style={{ fontSize: 11, color: \"var(--textColorSecondary)\", margin: \"8px 16px\" }}\n >\n {readActivity.map((read, index) => (\n <span\n key={index}\n title={`${read.method} · ${read.status === \"reading\" ? \"reading\" : read.status === \"ok\" ? \"read\" : \"unavailable\"}`}\n data-method={read.method}\n data-status={read.status}\n style={{ marginRight: 10 }}\n >\n <AiIcon\n material={\n read.status === \"reading\"\n ? \"sync\"\n : read.status === \"ok\"\n ? \"check_circle_outline\"\n : \"info_outline\"\n }\n size={13}\n />{\" \"}\n {read.method} ·{\" \"}\n {read.status === \"reading\" ? \"reading\" : read.status === \"ok\" ? \"read\" : \"unavailable\"}\n </span>\n ))}\n </div>\n )}\n {busy && (\n <p className=\"power-ai-thinking\" role=\"status\">\n {stopped.includes(key) ? \"Stopping response\" : \"Thinking\"}\n <span className=\"power-ai-dots\" aria-hidden=\"true\">\n <span>.</span>\n <span>.</span>\n <span>.</span>\n </span>\n </p>\n )}\n {!busy && stopped.includes(key) && (\n <p className=\"power-ai-cancellation\" role=\"status\">\n Response stopped{\" \"}\n <button\n type=\"button\"\n aria-label=\"Dismiss cancellation\"\n className=\"power-ai-dismiss\"\n title=\"Dismiss\"\n onClick={() => setStopped((keys) => keys.filter((entry) => entry !== key))}\n >\n <AiIcon material=\"close\" size={14} />\n </button>\n </p>\n )}\n {error && <p role=\"alert\">{error}</p>}\n </div>\n <form\n onSubmit={(event) => {\n event.preventDefault();\n void send();\n }}\n >\n {suggestions.length > 0 && (\n <div\n className=\"power-ai-autocomplete\"\n role=\"listbox\"\n id=\"power-ai-commands\"\n aria-label=\"Prompt shortcuts\"\n >\n {suggestions.map((shortcut, index) => (\n <button\n type=\"button\"\n role=\"option\"\n id={`power-ai-command-${index}`}\n aria-selected={index === suggestionIndex % suggestions.length}\n key={shortcut.id}\n title={`Insert /${shortcut.command}: ${shortcut.label}`}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => selectSuggestion(index)}\n >\n <span>/{shortcut.command}</span>\n <span>{shortcut.label}</span>\n </button>\n ))}\n </div>\n )}\n <AiContextPreview context={attachedAiContext(context)} />\n <AiTerminalContext\n clusterId={context.clusterId}\n attachment={terminalAttachment}\n onChange={setTerminalAttachment}\n disabled={busy}\n />\n <textarea\n ref={composer}\n aria-controls={suggestions.length ? \"power-ai-commands\" : undefined}\n aria-expanded={suggestions.length > 0}\n aria-activedescendant={\n suggestions.length ? `power-ai-command-${suggestionIndex % suggestions.length}` : undefined\n }\n autoFocus\n aria-label=\"Message\"\n placeholder=\"Ask about this cluster…\"\n onKeyDown={(event) => {\n if (event.nativeEvent.isComposing || event.keyCode === 229) return;\n if (suggestions.length && !event.shiftKey) {\n if (event.key === \"ArrowDown\" || event.key === \"ArrowUp\") {\n event.preventDefault();\n setSuggestionIndex(\n (index) =>\n (index + (event.key === \"ArrowDown\" ? 1 : suggestions.length - 1)) % suggestions.length,\n );\n return;\n }\n if (event.key === \"Enter\" || event.key === \"Tab\") {\n event.preventDefault();\n selectSuggestion(suggestionIndex % suggestions.length);\n return;\n }\n }\n if (\n event.key === \"Enter\" &&\n !event.shiftKey &&\n !event.nativeEvent.isComposing &&\n event.keyCode !== 229\n ) {\n event.preventDefault();\n if (!busy) void send();\n }\n }}\n value={draft}\n onChange={(event) => {\n setDraft(event.target.value);\n setSuggestionIndex(0);\n setDismissedDraft(undefined);\n }}\n disabled={busy}\n />\n <div className=\"power-ai-composer-footer\">\n <span>Enter to send · Shift+Enter for newline</span>\n {busy ? (\n <button\n type=\"button\"\n aria-label=\"Stop response\"\n disabled={stopped.includes(key)}\n onClick={stopResponse}\n >\n <AiIcon material=\"stop\" size={16} /> Stop\n </button>\n ) : (\n <button type=\"submit\" disabled={!draft.trim()} aria-label=\"Send\">\n <AiIcon material=\"send\" size={16} />\n </button>\n )}\n </div>\n </form>\n </aside>\n )}\n </>\n );\n});\n\nexport function startAiChat(isClusterDocument: () => boolean = isAiClusterDocument): () => void {\n const container = document.createElement(\"div\");\n container.dataset.freelensPowerAi = \"\";\n document.body.append(container);\n let mounted = false;\n let overviewActions: HTMLDivElement | undefined;\n let overviewIcon: HTMLSpanElement | undefined;\n let overviewLabel: HTMLSpanElement | undefined;\n let overviewResize: ResizeObserver | undefined;\n const updateOverviewLabel = () => {\n const overview = overviewActions?.nextElementSibling;\n const compact = Boolean(overview?.querySelector(\"[data-freelens-power-monitoring]\") && overview.clientWidth > 960);\n const label = compact ? \"Ask AI\" : \"Ask about cluster\";\n if (overviewLabel && overviewLabel.textContent !== label) overviewLabel.textContent = label;\n overviewActions?.querySelector(\"button\")?.setAttribute(\"aria-label\", compact ? \"Ask AI about cluster\" : label);\n };\n const removeOverview = () => {\n overviewResize?.disconnect();\n overviewResize = undefined;\n if (overviewIcon) ReactDOM.unmountComponentAtNode(overviewIcon);\n overviewIcon = undefined;\n overviewLabel = undefined;\n overviewActions?.remove();\n overviewActions = undefined;\n };\n const preferences = AiPreferencesStore.getInstanceOrCreate<AiPreferencesStore>();\n const reconcile = () => {\n const overview =\n preferences.enabled &&\n isClusterDocument() &&\n Renderer.Catalog.activeCluster.get() &&\n document.querySelector('[data-testid=\"cluster-overview-page\"]');\n if (!overview) {\n removeOverview();\n return;\n }\n if (overviewActions?.isConnected && overviewActions.nextElementSibling === overview) {\n updateOverviewLabel();\n return;\n }\n removeOverview();\n overviewActions = document.createElement(\"div\");\n overviewActions.className = \"power-ai-overview-actions\";\n const overviewButton = document.createElement(\"button\");\n overviewButton.type = \"button\";\n overviewButton.setAttribute(\"aria-label\", \"Ask about cluster\");\n overviewButton.title = \"Open the AI assistant to ask about this cluster\";\n overviewIcon = document.createElement(\"span\");\n overviewIcon.setAttribute(\"aria-hidden\", \"true\");\n overviewLabel = document.createElement(\"span\");\n overviewButton.append(overviewIcon, overviewLabel);\n overviewButton.onclick = () => window.dispatchEvent(new Event(\"power-ai-open\"));\n overviewActions.append(overviewButton);\n overview.before(overviewActions);\n updateOverviewLabel();\n if (typeof ResizeObserver !== \"undefined\") {\n overviewResize = new ResizeObserver(updateOverviewLabel);\n overviewResize.observe(overview);\n }\n ReactDOM.render(<AiIcon material=\"auto_awesome\" size={16} />, overviewIcon);\n };\n const observer = new MutationObserver(reconcile);\n const stop = autorun(() => {\n if (preferences.enabled && !mounted) {\n observer.observe(document.body, { childList: true, subtree: true });\n mounted = true;\n ReactDOM.render(<AiChat isClusterDocument={isClusterDocument} />, container);\n } else if (!preferences.enabled && mounted) {\n observer.disconnect();\n ReactDOM.unmountComponentAtNode(container);\n mounted = false;\n }\n reconcile();\n });\n return () => {\n stop();\n observer.disconnect();\n removeOverview();\n ReactDOM.unmountComponentAtNode(container);\n container.remove();\n };\n}\n"],"mappings":"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"}
@@ -13,6 +13,7 @@ function startAppearanceOverride() {
13
13
  style.textContent = `${color === "default" ? "" : `
14
14
  :root { --primary: ${color} !important; --buttonPrimaryBackground: ${color} !important; --menuSelectedOptionBgc: ${color} !important; --select-option-focused-bgc: color-mix(in srgb, ${color} 24%, var(--contentColor)) !important; --icon-focus-color: ${color} !important; }
15
15
  :root .Checkbox, :root .Drawer .drawer-title, :root .DrawerParamToggler .param-link { --blue: var(--primary); }
16
+ :root [role="treeitem"][class*="catalog-tree-module__selected--"] { --blue: var(--primary); }
16
17
  :root .Select:not(.Select--is-disabled) .Select__control--is-focused:not(.Select__control--is-disabled) { border-color: ${color} !important; box-shadow: 0 0 0 1px ${color} !important; }
17
18
  :root .Select__option--is-selected { background: var(--primary) !important; color: var(--textColorAccent) !important; }
18
19
  :root .NamespaceSelectMenu .Select__option { margin-block: 2px; }
@@ -1 +1 @@
1
- {"version":3,"file":"appearance.js","names":[],"sources":["../../src/renderer/appearance.ts"],"sourcesContent":["// SPDX-License-Identifier: Apache-2.0\nimport { reaction } from \"mobx\";\nimport { AppearancePreferencesStore, isAccentSelection } from \"../common/store/appearance-preferences-store\";\n\nexport function startAppearanceOverride(): () => void {\n const preferences = AppearancePreferencesStore.getInstanceOrCreate<AppearancePreferencesStore>();\n const style = document.createElement(\"style\");\n style.dataset.freelensPower = \"accent-color\";\n\n const stop = reaction(\n () => [preferences.enabled, preferences.accentColor] as const,\n ([enabled, color]) => {\n if (!enabled || !isAccentSelection(color)) {\n style.remove();\n return;\n }\n\n // [!important] takes precedence over the host theme's inline variables\n const accent =\n color === \"default\"\n ? \"\"\n : `\n :root { --primary: ${color} !important; --buttonPrimaryBackground: ${color} !important; --menuSelectedOptionBgc: ${color} !important; --select-option-focused-bgc: color-mix(in srgb, ${color} 24%, var(--contentColor)) !important; --icon-focus-color: ${color} !important; }\n :root .Checkbox, :root .Drawer .drawer-title, :root .DrawerParamToggler .param-link { --blue: var(--primary); }\n :root .Select:not(.Select--is-disabled) .Select__control--is-focused:not(.Select__control--is-disabled) { border-color: ${color} !important; box-shadow: 0 0 0 1px ${color} !important; }\n :root .Select__option--is-selected { background: var(--primary) !important; color: var(--textColorAccent) !important; }\n :root .NamespaceSelectMenu .Select__option { margin-block: 2px; }\n :root .NamespaceSelectMenu .Select__option--is-selected { background: color-mix(in srgb, var(--primary) 10%, var(--contentColor)) !important; color: var(--textColorAccent) !important; }\n :root .NamespaceSelectMenu .Select__option--is-selected.Select__option--is-focused { background: color-mix(in srgb, var(--primary) 24%, var(--contentColor)) !important; }\n :root .NamespaceSelectMenu .Select__option--is-selected .Icon { color: var(--primary); }\n :root a.link { color: var(--primary); }\n .Welcome [data-testid=\"no-welcome-banners-icon\"] svg path[fill=\"#23a49c\"] { fill: var(--primary); }\n `;\n style.textContent = `${accent}\\ninput[role=\"switch\"] { --track-color-active: var(--primary) !important; }`;\n\n if (!style.isConnected) {\n document.head.append(style);\n }\n },\n { fireImmediately: true },\n );\n\n return () => {\n stop();\n style.remove();\n };\n}\n"],"mappings":";;;AAIA,SAAgB,0BAAsC;CACpD,MAAM,cAAc,qCAAA,2BAA2B,oBAAgD;CAC/F,MAAM,QAAQ,SAAS,cAAc,OAAO;CAC5C,MAAM,QAAQ,gBAAgB;CAE9B,MAAM,OAAO,8BAAA,eACL,CAAC,YAAY,SAAS,YAAY,WAAW,IAClD,CAAC,SAAS,WAAW;EACpB,IAAI,CAAC,WAAW,CAAC,qCAAA,kBAAkB,KAAK,GAAG;GACzC,MAAM,OAAO;GACb;EACF;EAkBA,MAAM,cAAc,GAdlB,UAAU,YACN,KACA;6BACiB,MAAM,0CAA0C,MAAM,wCAAwC,MAAM,+DAA+D,MAAM,6DAA6D,MAAM;;kIAEvI,MAAM,qCAAqC,MAAM;;;;;;;;QAS/I;EAE9B,IAAI,CAAC,MAAM,aACT,SAAS,KAAK,OAAO,KAAK;CAE9B,GACA,EAAE,iBAAiB,KAAK,CAC1B;CAEA,aAAa;EACX,KAAK;EACL,MAAM,OAAO;CACf;AACF"}
1
+ {"version":3,"file":"appearance.js","names":[],"sources":["../../src/renderer/appearance.ts"],"sourcesContent":["// SPDX-License-Identifier: Apache-2.0\nimport { reaction } from \"mobx\";\nimport { AppearancePreferencesStore, isAccentSelection } from \"../common/store/appearance-preferences-store\";\n\nexport function startAppearanceOverride(): () => void {\n const preferences = AppearancePreferencesStore.getInstanceOrCreate<AppearancePreferencesStore>();\n const style = document.createElement(\"style\");\n style.dataset.freelensPower = \"accent-color\";\n\n const stop = reaction(\n () => [preferences.enabled, preferences.accentColor] as const,\n ([enabled, color]) => {\n if (!enabled || !isAccentSelection(color)) {\n style.remove();\n return;\n }\n\n // [!important] takes precedence over the host theme's inline variables\n const accent =\n color === \"default\"\n ? \"\"\n : `\n :root { --primary: ${color} !important; --buttonPrimaryBackground: ${color} !important; --menuSelectedOptionBgc: ${color} !important; --select-option-focused-bgc: color-mix(in srgb, ${color} 24%, var(--contentColor)) !important; --icon-focus-color: ${color} !important; }\n :root .Checkbox, :root .Drawer .drawer-title, :root .DrawerParamToggler .param-link { --blue: var(--primary); }\n :root [role=\"treeitem\"][class*=\"catalog-tree-module__selected--\"] { --blue: var(--primary); }\n :root .Select:not(.Select--is-disabled) .Select__control--is-focused:not(.Select__control--is-disabled) { border-color: ${color} !important; box-shadow: 0 0 0 1px ${color} !important; }\n :root .Select__option--is-selected { background: var(--primary) !important; color: var(--textColorAccent) !important; }\n :root .NamespaceSelectMenu .Select__option { margin-block: 2px; }\n :root .NamespaceSelectMenu .Select__option--is-selected { background: color-mix(in srgb, var(--primary) 10%, var(--contentColor)) !important; color: var(--textColorAccent) !important; }\n :root .NamespaceSelectMenu .Select__option--is-selected.Select__option--is-focused { background: color-mix(in srgb, var(--primary) 24%, var(--contentColor)) !important; }\n :root .NamespaceSelectMenu .Select__option--is-selected .Icon { color: var(--primary); }\n :root a.link { color: var(--primary); }\n .Welcome [data-testid=\"no-welcome-banners-icon\"] svg path[fill=\"#23a49c\"] { fill: var(--primary); }\n `;\n style.textContent = `${accent}\\ninput[role=\"switch\"] { --track-color-active: var(--primary) !important; }`;\n\n if (!style.isConnected) {\n document.head.append(style);\n }\n },\n { fireImmediately: true },\n );\n\n return () => {\n stop();\n style.remove();\n };\n}\n"],"mappings":";;;AAIA,SAAgB,0BAAsC;CACpD,MAAM,cAAc,qCAAA,2BAA2B,oBAAgD;CAC/F,MAAM,QAAQ,SAAS,cAAc,OAAO;CAC5C,MAAM,QAAQ,gBAAgB;CAE9B,MAAM,OAAO,8BAAA,eACL,CAAC,YAAY,SAAS,YAAY,WAAW,IAClD,CAAC,SAAS,WAAW;EACpB,IAAI,CAAC,WAAW,CAAC,qCAAA,kBAAkB,KAAK,GAAG;GACzC,MAAM,OAAO;GACb;EACF;EAmBA,MAAM,cAAc,GAflB,UAAU,YACN,KACA;6BACiB,MAAM,0CAA0C,MAAM,wCAAwC,MAAM,+DAA+D,MAAM,6DAA6D,MAAM;;;kIAGvI,MAAM,qCAAqC,MAAM;;;;;;;;QAS/I;EAE9B,IAAI,CAAC,MAAM,aACT,SAAS,KAAK,OAAO,KAAK;CAE9B,GACA,EAAE,iBAAiB,KAAK,CAC1B;CAEA,aAAa;EACX,KAAK;EACL,MAAM,OAAO;CACf;AACF"}